Update clang-format
This commit is contained in:
parent
c755a885bf
commit
9f18b7f4d8
89 changed files with 11377 additions and 11546 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -8,134 +8,134 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <type_safe/reference.hpp>
|
||||
#include <type_safe/flag_set.hpp>
|
||||
#include <type_safe/reference.hpp>
|
||||
|
||||
#include <cppast/detail/assert.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// The C++ standard that should be used.
|
||||
enum class cpp_standard
|
||||
/// The C++ standard that should be used.
|
||||
enum class cpp_standard
|
||||
{
|
||||
cpp_98,
|
||||
cpp_03,
|
||||
cpp_11,
|
||||
cpp_14,
|
||||
|
||||
cpp_1z, //< Upcoming C++17 (experimental).
|
||||
|
||||
cpp_latest = cpp_standard::cpp_14, //< The latest supported C++ standard.
|
||||
};
|
||||
|
||||
/// \returns A human readable string representing the option,
|
||||
/// it is e.g. `c++14` for `cpp_14`.
|
||||
inline const char* to_string(cpp_standard standard) noexcept
|
||||
{
|
||||
switch (standard)
|
||||
{
|
||||
cpp_98,
|
||||
cpp_03,
|
||||
cpp_11,
|
||||
cpp_14,
|
||||
|
||||
cpp_1z, //< Upcoming C++17 (experimental).
|
||||
|
||||
cpp_latest = cpp_standard::cpp_14, //< The latest supported C++ standard.
|
||||
};
|
||||
|
||||
/// \returns A human readable string representing the option,
|
||||
/// it is e.g. `c++14` for `cpp_14`.
|
||||
inline const char* to_string(cpp_standard standard) noexcept
|
||||
{
|
||||
switch (standard)
|
||||
{
|
||||
case cpp_standard::cpp_98:
|
||||
return "c++98";
|
||||
case cpp_standard::cpp_03:
|
||||
return "c++03";
|
||||
case cpp_standard::cpp_11:
|
||||
return "c++11";
|
||||
case cpp_standard::cpp_14:
|
||||
return "c++14";
|
||||
case cpp_standard::cpp_1z:
|
||||
return "c++1z";
|
||||
}
|
||||
|
||||
DEBUG_UNREACHABLE(detail::assert_handler{});
|
||||
return "ups";
|
||||
case cpp_standard::cpp_98:
|
||||
return "c++98";
|
||||
case cpp_standard::cpp_03:
|
||||
return "c++03";
|
||||
case cpp_standard::cpp_11:
|
||||
return "c++11";
|
||||
case cpp_standard::cpp_14:
|
||||
return "c++14";
|
||||
case cpp_standard::cpp_1z:
|
||||
return "c++1z";
|
||||
}
|
||||
|
||||
/// Other special compilation flags.
|
||||
enum class compile_flag
|
||||
DEBUG_UNREACHABLE(detail::assert_handler{});
|
||||
return "ups";
|
||||
}
|
||||
|
||||
/// Other special compilation flags.
|
||||
enum class compile_flag
|
||||
{
|
||||
gnu_extensions, //< Enable GCC extensions.
|
||||
|
||||
ms_extensions, //< Enable MSVC extensions.
|
||||
ms_compatibility, //< Enable MSVC compatibility.
|
||||
|
||||
_flag_set_size, //< \exclude
|
||||
};
|
||||
|
||||
/// A [ts::flag_set]() of [cppast::compile_flag]().
|
||||
using compile_flags = type_safe::flag_set<compile_flag>;
|
||||
|
||||
/// Base class for the configuration of a [cppast::parser]().
|
||||
class compile_config
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the given C++ standard and compilation flags.
|
||||
void set_flags(cpp_standard standard, compile_flags flags = {})
|
||||
{
|
||||
gnu_extensions, //< Enable GCC extensions.
|
||||
do_set_flags(standard, flags);
|
||||
}
|
||||
|
||||
ms_extensions, //< Enable MSVC extensions.
|
||||
ms_compatibility, //< Enable MSVC compatibility.
|
||||
|
||||
_flag_set_size, //< \exclude
|
||||
};
|
||||
|
||||
/// A [ts::flag_set]() of [cppast::compile_flag]().
|
||||
using compile_flags = type_safe::flag_set<compile_flag>;
|
||||
|
||||
/// Base class for the configuration of a [cppast::parser]().
|
||||
class compile_config
|
||||
/// \effects Adds the given path to the set of include directories.
|
||||
void add_include_dir(std::string path)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the given C++ standard and compilation flags.
|
||||
void set_flags(cpp_standard standard, compile_flags flags = {})
|
||||
{
|
||||
do_set_flags(standard, flags);
|
||||
}
|
||||
do_add_include_dir(std::move(path));
|
||||
}
|
||||
|
||||
/// \effects Adds the given path to the set of include directories.
|
||||
void add_include_dir(std::string path)
|
||||
{
|
||||
do_add_include_dir(std::move(path));
|
||||
}
|
||||
/// \effects Defines the given macro.
|
||||
void define_macro(std::string name, std::string definition)
|
||||
{
|
||||
do_add_macro_definition(std::move(name), std::move(definition));
|
||||
}
|
||||
|
||||
/// \effects Defines the given macro.
|
||||
void define_macro(std::string name, std::string definition)
|
||||
{
|
||||
do_add_macro_definition(std::move(name), std::move(definition));
|
||||
}
|
||||
/// \effects Undefines the given macro.
|
||||
void undefine_macro(std::string name)
|
||||
{
|
||||
do_remove_macro_definition(std::move(name));
|
||||
}
|
||||
|
||||
/// \effects Undefines the given macro.
|
||||
void undefine_macro(std::string name)
|
||||
{
|
||||
do_remove_macro_definition(std::move(name));
|
||||
}
|
||||
/// \returns A unique name of the configuration.
|
||||
/// \notes This allows detecting mismatches of configurations and parsers.
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return do_get_name();
|
||||
}
|
||||
|
||||
/// \returns A unique name of the configuration.
|
||||
/// \notes This allows detecting mismatches of configurations and parsers.
|
||||
const char* name() const noexcept
|
||||
{
|
||||
return do_get_name();
|
||||
}
|
||||
protected:
|
||||
compile_config(std::vector<std::string> def_flags) : flags_(std::move(def_flags)) {}
|
||||
|
||||
protected:
|
||||
compile_config(std::vector<std::string> def_flags) : flags_(std::move(def_flags)) {}
|
||||
compile_config(const compile_config&) = default;
|
||||
compile_config& operator=(const compile_config&) = default;
|
||||
|
||||
compile_config(const compile_config&) = default;
|
||||
compile_config& operator=(const compile_config&) = default;
|
||||
~compile_config() noexcept = default;
|
||||
|
||||
~compile_config() noexcept = default;
|
||||
void add_flag(std::string flag)
|
||||
{
|
||||
flags_.push_back(std::move(flag));
|
||||
}
|
||||
|
||||
void add_flag(std::string flag)
|
||||
{
|
||||
flags_.push_back(std::move(flag));
|
||||
}
|
||||
const std::vector<std::string>& get_flags() const noexcept
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& get_flags() const noexcept
|
||||
{
|
||||
return flags_;
|
||||
}
|
||||
private:
|
||||
/// \effects Sets the given C++ standard and compilation flags.
|
||||
virtual void do_set_flags(cpp_standard standard, compile_flags flags) = 0;
|
||||
|
||||
private:
|
||||
/// \effects Sets the given C++ standard and compilation flags.
|
||||
virtual void do_set_flags(cpp_standard standard, compile_flags flags) = 0;
|
||||
/// \effects Adds the given path to the set of include directories.
|
||||
virtual void do_add_include_dir(std::string path) = 0;
|
||||
|
||||
/// \effects Adds the given path to the set of include directories.
|
||||
virtual void do_add_include_dir(std::string path) = 0;
|
||||
/// \effects Defines the given macro.
|
||||
virtual void do_add_macro_definition(std::string name, std::string definition) = 0;
|
||||
|
||||
/// \effects Defines the given macro.
|
||||
virtual void do_add_macro_definition(std::string name, std::string definition) = 0;
|
||||
/// \effects Undefines the given macro.
|
||||
virtual void do_remove_macro_definition(std::string name) = 0;
|
||||
|
||||
/// \effects Undefines the given macro.
|
||||
virtual void do_remove_macro_definition(std::string name) = 0;
|
||||
/// \returns A unique name of the configuration.
|
||||
/// \notes This allows detecting mismatches of configurations and parsers.
|
||||
virtual const char* do_get_name() const noexcept = 0;
|
||||
|
||||
/// \returns A unique name of the configuration.
|
||||
/// \notes This allows detecting mismatches of configurations and parsers.
|
||||
virtual const char* do_get_name() const noexcept = 0;
|
||||
|
||||
std::vector<std::string> flags_;
|
||||
};
|
||||
std::vector<std::string> flags_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_COMPILE_CONFIG_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,35 +10,34 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a C++ alias template.
|
||||
class cpp_alias_template final : public cpp_template
|
||||
/// A [cppast::cpp_entity]() modelling a C++ alias template.
|
||||
class cpp_alias_template final : public cpp_template
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_alias_template]().
|
||||
class builder : public basic_builder<cpp_alias_template, cpp_type_alias>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_alias_template]().
|
||||
class builder : public basic_builder<cpp_alias_template, cpp_type_alias>
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// \returns A reference to the type alias that is being templated.
|
||||
const cpp_type_alias& type_alias() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_type_alias&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_alias_template(std::unique_ptr<cpp_type_alias> alias)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(alias.release()))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_alias_template, cpp_type_alias>;
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// \returns A reference to the type alias that is being templated.
|
||||
const cpp_type_alias& type_alias() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_type_alias&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_alias_template(std::unique_ptr<cpp_type_alias> alias)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(alias.release()))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_alias_template, cpp_type_alias>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,46 +10,45 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// An array of a [cppast::cpp_type]().
|
||||
class cpp_array_type final : public cpp_type
|
||||
/// An array of a [cppast::cpp_type]().
|
||||
class cpp_array_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created array.
|
||||
/// \notes `size` may be `nullptr`.
|
||||
static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> size)
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created array.
|
||||
/// \notes `size` may be `nullptr`.
|
||||
static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> size)
|
||||
{
|
||||
return std::unique_ptr<cpp_array_type>(
|
||||
new cpp_array_type(std::move(type), std::move(size)));
|
||||
}
|
||||
return std::unique_ptr<cpp_array_type>(
|
||||
new cpp_array_type(std::move(type), std::move(size)));
|
||||
}
|
||||
|
||||
/// \returns A reference to the value [cppast::cpp_type]().
|
||||
const cpp_type& value_type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
/// \returns A reference to the value [cppast::cpp_type]().
|
||||
const cpp_type& value_type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the array.
|
||||
/// \notes An unsized array - `T[]` - does not have a size.
|
||||
type_safe::optional_ref<const cpp_expression> size() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(size_.get());
|
||||
}
|
||||
/// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the
|
||||
/// array. \notes An unsized array - `T[]` - does not have a size.
|
||||
type_safe::optional_ref<const cpp_expression> size() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(size_.get());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_array_type(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> size)
|
||||
: type_(std::move(type)), size_(std::move(size))
|
||||
{
|
||||
}
|
||||
private:
|
||||
cpp_array_type(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> size)
|
||||
: type_(std::move(type)), size_(std::move(size))
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::array_t;
|
||||
}
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::array_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
std::unique_ptr<cpp_expression> size_;
|
||||
};
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
std::unique_ptr<cpp_expression> size_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -15,109 +15,107 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// The known C++ attributes.
|
||||
enum class cpp_attribute_kind
|
||||
/// The known C++ attributes.
|
||||
enum class cpp_attribute_kind
|
||||
{
|
||||
// update get_attribute_kind() in tokenizer, when updating this
|
||||
|
||||
alignas_,
|
||||
carries_dependency,
|
||||
deprecated,
|
||||
fallthrough,
|
||||
maybe_unused,
|
||||
nodiscard,
|
||||
noreturn,
|
||||
|
||||
unknown, //< An unknown attribute.
|
||||
};
|
||||
|
||||
/// A C++ attribute, including `alignas` specifiers.
|
||||
///
|
||||
/// It consists of a name, an optional namespace scope and optional arguments.
|
||||
/// The scope is just a single identifier and doesn't include the `::` and can be given explicitly
|
||||
/// or via using. The arguments are as specified in the source code but do not include the
|
||||
/// outer-most `(` and `)`. It can also be variadic or not.
|
||||
///
|
||||
/// An attribute can be known or unknown.
|
||||
/// A known attribute will have the [cppast::cpp_attribute_kind]() set properly.
|
||||
class cpp_attribute
|
||||
{
|
||||
public:
|
||||
/// \effects Creates a known attribute, potentially with arguments.
|
||||
cpp_attribute(cpp_attribute_kind kind, type_safe::optional<cpp_token_string> arguments);
|
||||
|
||||
/// \effects Creates an unknown attribute giving it the optional scope, names, arguments and
|
||||
/// whether it is variadic.
|
||||
cpp_attribute(type_safe::optional<std::string> scope, std::string name,
|
||||
type_safe::optional<cpp_token_string> arguments, bool is_variadic)
|
||||
: scope_(std::move(scope)), arguments_(std::move(arguments)), name_(std::move(name)),
|
||||
variadic_(is_variadic)
|
||||
{}
|
||||
|
||||
/// \returns The kind of attribute, if it is known.
|
||||
const cpp_attribute_kind& kind() const noexcept
|
||||
{
|
||||
// update get_attribute_kind() in tokenizer, when updating this
|
||||
return kind_;
|
||||
}
|
||||
|
||||
alignas_,
|
||||
carries_dependency,
|
||||
deprecated,
|
||||
fallthrough,
|
||||
maybe_unused,
|
||||
nodiscard,
|
||||
noreturn,
|
||||
|
||||
unknown, //< An unknown attribute.
|
||||
};
|
||||
|
||||
/// A C++ attribute, including `alignas` specifiers.
|
||||
///
|
||||
/// It consists of a name, an optional namespace scope and optional arguments.
|
||||
/// The scope is just a single identifier and doesn't include the `::` and can be given explicitly or via using.
|
||||
/// The arguments are as specified in the source code but do not include the outer-most `(` and `)`.
|
||||
/// It can also be variadic or not.
|
||||
///
|
||||
/// An attribute can be known or unknown.
|
||||
/// A known attribute will have the [cppast::cpp_attribute_kind]() set properly.
|
||||
class cpp_attribute
|
||||
/// \returns The name of the attribute.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \effects Creates a known attribute, potentially with arguments.
|
||||
cpp_attribute(cpp_attribute_kind kind, type_safe::optional<cpp_token_string> arguments);
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \effects Creates an unknown attribute giving it the optional scope, names, arguments and whether it is variadic.
|
||||
cpp_attribute(type_safe::optional<std::string> scope, std::string name,
|
||||
type_safe::optional<cpp_token_string> arguments, bool is_variadic)
|
||||
: scope_(std::move(scope)),
|
||||
arguments_(std::move(arguments)),
|
||||
name_(std::move(name)),
|
||||
variadic_(is_variadic)
|
||||
{
|
||||
}
|
||||
/// \returns The scope of the attribute, if there is any.
|
||||
const type_safe::optional<std::string>& scope() const noexcept
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
/// \returns The kind of attribute, if it is known.
|
||||
const cpp_attribute_kind& kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
/// \returns Whether or not the attribute is variadic.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
|
||||
/// \returns The name of the attribute.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
/// \returns The arguments of the attribute, if they are any.
|
||||
const type_safe::optional<cpp_token_string>& arguments() const noexcept
|
||||
{
|
||||
return arguments_;
|
||||
}
|
||||
|
||||
/// \returns The scope of the attribute, if there is any.
|
||||
const type_safe::optional<std::string>& scope() const noexcept
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
private:
|
||||
type_safe::optional<std::string> scope_;
|
||||
type_safe::optional<cpp_token_string> arguments_;
|
||||
std::string name_;
|
||||
cpp_attribute_kind kind_ = cpp_attribute_kind::unknown;
|
||||
bool variadic_;
|
||||
};
|
||||
|
||||
/// \returns Whether or not the attribute is variadic.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
/// A list of C++ attributes.
|
||||
using cpp_attribute_list = std::vector<cpp_attribute>;
|
||||
|
||||
/// \returns The arguments of the attribute, if they are any.
|
||||
const type_safe::optional<cpp_token_string>& arguments() const noexcept
|
||||
{
|
||||
return arguments_;
|
||||
}
|
||||
/// Checks whether an attribute is given.
|
||||
/// \returns `true` if the given attribute list (1-2) / entity (3-4) contain
|
||||
/// an attribute of the given name (1+3) / kind (2+4).
|
||||
/// `false` otherwise.
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
|
||||
const std::string& name);
|
||||
|
||||
private:
|
||||
type_safe::optional<std::string> scope_;
|
||||
type_safe::optional<cpp_token_string> arguments_;
|
||||
std::string name_;
|
||||
cpp_attribute_kind kind_ = cpp_attribute_kind::unknown;
|
||||
bool variadic_;
|
||||
};
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
|
||||
cpp_attribute_kind kind);
|
||||
|
||||
/// A list of C++ attributes.
|
||||
using cpp_attribute_list = std::vector<cpp_attribute>;
|
||||
class cpp_entity;
|
||||
|
||||
/// Checks whether an attribute is given.
|
||||
/// \returns `true` if the given attribute list (1-2) / entity (3-4) contain
|
||||
/// an attribute of the given name (1+3) / kind (2+4).
|
||||
/// `false` otherwise.
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
|
||||
const std::string& name);
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
|
||||
const std::string& name);
|
||||
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
|
||||
cpp_attribute_kind kind);
|
||||
|
||||
class cpp_entity;
|
||||
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
|
||||
const std::string& name);
|
||||
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
|
||||
cpp_attribute_kind kind);
|
||||
/// \group has_attribute
|
||||
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
|
||||
cpp_attribute_kind kind);
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -12,239 +12,233 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// The keyword used on the declaration of a [cppast::cpp_class]().
|
||||
enum class cpp_class_kind
|
||||
/// The keyword used on the declaration of a [cppast::cpp_class]().
|
||||
enum class cpp_class_kind
|
||||
{
|
||||
class_t,
|
||||
struct_t,
|
||||
union_t,
|
||||
};
|
||||
|
||||
/// \returns The keyword as a string.
|
||||
const char* to_string(cpp_class_kind kind) noexcept;
|
||||
|
||||
/// The C++ access specifiers.
|
||||
enum cpp_access_specifier_kind : int
|
||||
{
|
||||
cpp_public,
|
||||
cpp_protected,
|
||||
cpp_private
|
||||
};
|
||||
|
||||
/// \returns The access specifier keyword as a string.
|
||||
const char* to_string(cpp_access_specifier_kind access) noexcept;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ access specifier.
|
||||
class cpp_access_specifier final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created access specifier.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_access_specifier> build(cpp_access_specifier_kind kind)
|
||||
{
|
||||
class_t,
|
||||
struct_t,
|
||||
union_t,
|
||||
};
|
||||
return std::unique_ptr<cpp_access_specifier>(new cpp_access_specifier(kind));
|
||||
}
|
||||
|
||||
/// \returns The keyword as a string.
|
||||
const char* to_string(cpp_class_kind kind) noexcept;
|
||||
|
||||
/// The C++ access specifiers.
|
||||
enum cpp_access_specifier_kind : int
|
||||
/// \returns The kind of access specifier.
|
||||
cpp_access_specifier_kind access_specifier() const noexcept
|
||||
{
|
||||
cpp_public,
|
||||
cpp_protected,
|
||||
cpp_private
|
||||
};
|
||||
return access_;
|
||||
}
|
||||
|
||||
/// \returns The access specifier keyword as a string.
|
||||
const char* to_string(cpp_access_specifier_kind access) noexcept;
|
||||
private:
|
||||
cpp_access_specifier(cpp_access_specifier_kind access)
|
||||
: cpp_entity(to_string(access)), access_(access)
|
||||
{}
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ access specifier.
|
||||
class cpp_access_specifier final : public cpp_entity
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_access_specifier_kind access_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a base class specifier.
|
||||
class cpp_base_class final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created base class specifier.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to the specifier itself.
|
||||
static std::unique_ptr<cpp_base_class> build(std::string name, std::unique_ptr<cpp_type> base,
|
||||
cpp_access_specifier_kind access, bool is_virtual)
|
||||
{
|
||||
return std::unique_ptr<cpp_base_class>(
|
||||
new cpp_base_class(std::move(name), std::move(base), access, is_virtual));
|
||||
}
|
||||
|
||||
/// \returns The type of the base class.
|
||||
const cpp_type& type() const
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns The access specifier of the base class.
|
||||
cpp_access_specifier_kind access_specifier() const noexcept
|
||||
{
|
||||
return access_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is a `virtual` base class.
|
||||
bool is_virtual() const noexcept
|
||||
{
|
||||
return virtual_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_base_class(std::string name, std::unique_ptr<cpp_type> base,
|
||||
cpp_access_specifier_kind access, bool is_virtual)
|
||||
: cpp_entity(std::move(name)), type_(std::move(base)), access_(access), virtual_(is_virtual)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
cpp_access_specifier_kind access_;
|
||||
bool virtual_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ class.
|
||||
///
|
||||
/// This can either be a definition or just a forward declaration.
|
||||
/// If it is just a forward declaration,
|
||||
/// everything except the class type will not be available.
|
||||
class cpp_class final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_class, cpp_entity>,
|
||||
public cpp_forward_declarable
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_class]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Sets the name and kind and whether it is `final`.
|
||||
explicit builder(std::string name, cpp_class_kind kind, bool is_final = false)
|
||||
: class_(new cpp_class(std::move(name), kind, is_final))
|
||||
{}
|
||||
|
||||
/// \returns A newly created access specifier.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_access_specifier> build(cpp_access_specifier_kind kind)
|
||||
/// \effects Marks the class as final.
|
||||
void is_final() noexcept
|
||||
{
|
||||
return std::unique_ptr<cpp_access_specifier>(new cpp_access_specifier(kind));
|
||||
class_->final_ = true;
|
||||
}
|
||||
|
||||
/// \returns The kind of access specifier.
|
||||
cpp_access_specifier_kind access_specifier() const noexcept
|
||||
/// \effects Builds a [cppast::cpp_base_class]() and adds it.
|
||||
cpp_base_class& base_class(std::string name, std::unique_ptr<cpp_type> type,
|
||||
cpp_access_specifier_kind access, bool is_virtual)
|
||||
{
|
||||
return access_;
|
||||
return add_base_class(
|
||||
cpp_base_class::build(std::move(name), std::move(type), access, is_virtual));
|
||||
}
|
||||
|
||||
/// \effects Adds a new base class.
|
||||
cpp_base_class& add_base_class(std::unique_ptr<cpp_base_class> base) noexcept
|
||||
{
|
||||
auto bptr = base.get();
|
||||
class_->bases_.push_back(*class_, std::move(base));
|
||||
return *bptr;
|
||||
}
|
||||
|
||||
/// \effects Builds a [cppast::cpp_access_specifier]() and adds it.
|
||||
void access_specifier(cpp_access_specifier_kind access)
|
||||
{
|
||||
add_child(cpp_access_specifier::build(access));
|
||||
}
|
||||
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
class_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished class.
|
||||
cpp_class& get() noexcept
|
||||
{
|
||||
return *class_;
|
||||
}
|
||||
|
||||
/// \effects Registers the class in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished class.
|
||||
std::unique_ptr<cpp_class> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||
|
||||
/// \effects Marks the class as forward declaration.
|
||||
/// \returns The finished class.
|
||||
std::unique_ptr<cpp_class> finish_declaration(const cpp_entity_index& idx,
|
||||
cpp_entity_id definition_id);
|
||||
|
||||
/// \effects Returns the finished class without registering it.
|
||||
/// \notes This is intended for templated classes only.
|
||||
std::unique_ptr<cpp_class> finish(type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||
|
||||
/// \effects Returns the finish class without registering it and marks it as forward
|
||||
/// declaration. \notes This is intended for templated classes only.
|
||||
std::unique_ptr<cpp_class> finish_declaration(cpp_entity_id definition_id);
|
||||
|
||||
private:
|
||||
cpp_access_specifier(cpp_access_specifier_kind access)
|
||||
: cpp_entity(to_string(access)), access_(access)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_access_specifier_kind access_;
|
||||
std::unique_ptr<cpp_class> class_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a base class specifier.
|
||||
class cpp_base_class final : public cpp_entity
|
||||
/// \returns The keyword used in the declaration of the class.
|
||||
cpp_class_kind class_kind() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return kind_;
|
||||
}
|
||||
|
||||
/// \returns A newly created base class specifier.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to the specifier itself.
|
||||
static std::unique_ptr<cpp_base_class> build(std::string name,
|
||||
std::unique_ptr<cpp_type> base,
|
||||
cpp_access_specifier_kind access,
|
||||
bool is_virtual)
|
||||
{
|
||||
return std::unique_ptr<cpp_base_class>(
|
||||
new cpp_base_class(std::move(name), std::move(base), access, is_virtual));
|
||||
}
|
||||
|
||||
/// \returns The type of the base class.
|
||||
const cpp_type& type() const
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns The access specifier of the base class.
|
||||
cpp_access_specifier_kind access_specifier() const noexcept
|
||||
{
|
||||
return access_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is a `virtual` base class.
|
||||
bool is_virtual() const noexcept
|
||||
{
|
||||
return virtual_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_base_class(std::string name, std::unique_ptr<cpp_type> base,
|
||||
cpp_access_specifier_kind access, bool is_virtual)
|
||||
: cpp_entity(std::move(name)), type_(std::move(base)), access_(access), virtual_(is_virtual)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
cpp_access_specifier_kind access_;
|
||||
bool virtual_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ class.
|
||||
///
|
||||
/// This can either be a definition or just a forward declaration.
|
||||
/// If it is just a forward declaration,
|
||||
/// everything except the class type will not be available.
|
||||
class cpp_class final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_class, cpp_entity>,
|
||||
public cpp_forward_declarable
|
||||
/// \returns Whether or not the class was declared `final`.
|
||||
bool is_final() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return final_;
|
||||
}
|
||||
|
||||
/// Builds a [cppast::cpp_class]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name and kind and whether it is `final`.
|
||||
explicit builder(std::string name, cpp_class_kind kind, bool is_final = false)
|
||||
: class_(new cpp_class(std::move(name), kind, is_final))
|
||||
{
|
||||
}
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_base_class]() specifiers.
|
||||
detail::iteratable_intrusive_list<cpp_base_class> bases() const noexcept
|
||||
{
|
||||
return type_safe::ref(bases_);
|
||||
}
|
||||
|
||||
/// \effects Marks the class as final.
|
||||
void is_final() noexcept
|
||||
{
|
||||
class_->final_ = true;
|
||||
}
|
||||
private:
|
||||
cpp_class(std::string name, cpp_class_kind kind, bool final)
|
||||
: cpp_entity(std::move(name)), kind_(kind), final_(final)
|
||||
{}
|
||||
|
||||
/// \effects Builds a [cppast::cpp_base_class]() and adds it.
|
||||
cpp_base_class& base_class(std::string name, std::unique_ptr<cpp_type> type,
|
||||
cpp_access_specifier_kind access, bool is_virtual)
|
||||
{
|
||||
return add_base_class(
|
||||
cpp_base_class::build(std::move(name), std::move(type), access, is_virtual));
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
/// \effects Adds a new base class.
|
||||
cpp_base_class& add_base_class(std::unique_ptr<cpp_base_class> base) noexcept
|
||||
{
|
||||
auto bptr = base.get();
|
||||
class_->bases_.push_back(*class_, std::move(base));
|
||||
return *bptr;
|
||||
}
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return type_safe::ref(*this);
|
||||
}
|
||||
|
||||
/// \effects Builds a [cppast::cpp_access_specifier]() and adds it.
|
||||
void access_specifier(cpp_access_specifier_kind access)
|
||||
{
|
||||
add_child(cpp_access_specifier::build(access));
|
||||
}
|
||||
detail::intrusive_list<cpp_base_class> bases_;
|
||||
cpp_class_kind kind_;
|
||||
bool final_;
|
||||
};
|
||||
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
class_->add_child(std::move(child));
|
||||
}
|
||||
/// \returns The type the base class refers to.
|
||||
/// It is either a class or some form of typedef.
|
||||
type_safe::optional_ref<const cpp_entity> get_class_or_typedef(const cpp_entity_index& index,
|
||||
const cpp_base_class& base);
|
||||
|
||||
/// \returns The not yet finished class.
|
||||
cpp_class& get() noexcept
|
||||
{
|
||||
return *class_;
|
||||
}
|
||||
|
||||
/// \effects Registers the class in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished class.
|
||||
std::unique_ptr<cpp_class> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||
|
||||
/// \effects Marks the class as forward declaration.
|
||||
/// \returns The finished class.
|
||||
std::unique_ptr<cpp_class> finish_declaration(const cpp_entity_index& idx,
|
||||
cpp_entity_id definition_id);
|
||||
|
||||
/// \effects Returns the finished class without registering it.
|
||||
/// \notes This is intended for templated classes only.
|
||||
std::unique_ptr<cpp_class> finish(type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||
|
||||
/// \effects Returns the finish class without registering it and marks it as forward declaration.
|
||||
/// \notes This is intended for templated classes only.
|
||||
std::unique_ptr<cpp_class> finish_declaration(cpp_entity_id definition_id);
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_class> class_;
|
||||
};
|
||||
|
||||
/// \returns The keyword used in the declaration of the class.
|
||||
cpp_class_kind class_kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the class was declared `final`.
|
||||
bool is_final() const noexcept
|
||||
{
|
||||
return final_;
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_base_class]() specifiers.
|
||||
detail::iteratable_intrusive_list<cpp_base_class> bases() const noexcept
|
||||
{
|
||||
return type_safe::ref(bases_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_class(std::string name, cpp_class_kind kind, bool final)
|
||||
: cpp_entity(std::move(name)), kind_(kind), final_(final)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return type_safe::ref(*this);
|
||||
}
|
||||
|
||||
detail::intrusive_list<cpp_base_class> bases_;
|
||||
cpp_class_kind kind_;
|
||||
bool final_;
|
||||
};
|
||||
|
||||
/// \returns The type the base class refers to.
|
||||
/// It is either a class or some form of typedef.
|
||||
type_safe::optional_ref<const cpp_entity> get_class_or_typedef(const cpp_entity_index& index,
|
||||
const cpp_base_class& base);
|
||||
|
||||
/// \returns The type the base class refers to.
|
||||
/// Typedefs are unwrapped.
|
||||
type_safe::optional_ref<const cpp_class> get_class(const cpp_entity_index& index,
|
||||
const cpp_base_class& base);
|
||||
/// \returns The type the base class refers to.
|
||||
/// Typedefs are unwrapped.
|
||||
type_safe::optional_ref<const cpp_class> get_class(const cpp_entity_index& index,
|
||||
const cpp_base_class& base);
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_CLASS_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,65 +10,63 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a class template.
|
||||
class cpp_class_template final : public cpp_template
|
||||
/// A [cppast::cpp_entity]() modelling a class template.
|
||||
class cpp_class_template final : public cpp_template
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_class_template]().
|
||||
class builder : public basic_builder<cpp_class_template, cpp_class>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_class_template]().
|
||||
class builder : public basic_builder<cpp_class_template, cpp_class>
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// A reference to the class that is being templated.
|
||||
const cpp_class& class_() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_class&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_class_template(std::unique_ptr<cpp_class> func)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(func.release()))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_class_template, cpp_class>;
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a class template specialization.
|
||||
class cpp_class_template_specialization final : public cpp_template_specialization
|
||||
/// A reference to the class that is being templated.
|
||||
const cpp_class& class_() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_class&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_class_template(std::unique_ptr<cpp_class> func)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(func.release()))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_class_template, cpp_class>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a class template specialization.
|
||||
class cpp_class_template_specialization final : public cpp_template_specialization
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_class_template_specialization]().
|
||||
class builder : public specialization_builder<cpp_class_template_specialization, cpp_class>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_class_template_specialization]().
|
||||
class builder : public specialization_builder<cpp_class_template_specialization, cpp_class>
|
||||
{
|
||||
public:
|
||||
using specialization_builder::specialization_builder;
|
||||
};
|
||||
|
||||
/// A reference to the class that is being specialized.
|
||||
const cpp_class& class_() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_class&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_class_template_specialization(std::unique_ptr<cpp_class> func, cpp_template_ref primary)
|
||||
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend specialization_builder<cpp_class_template_specialization, cpp_class>;
|
||||
using specialization_builder::specialization_builder;
|
||||
};
|
||||
|
||||
/// A reference to the class that is being specialized.
|
||||
const cpp_class& class_() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_class&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_class_template_specialization(std::unique_ptr<cpp_class> func, cpp_template_ref primary)
|
||||
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend specialization_builder<cpp_class_template_specialization, cpp_class>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,51 +10,51 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_type]() that isn't given but taken from an expression.
|
||||
class cpp_decltype_type final : public cpp_type
|
||||
/// A [cppast::cpp_type]() that isn't given but taken from an expression.
|
||||
class cpp_decltype_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `decltype` type.
|
||||
static std::unique_ptr<cpp_decltype_type> build(std::unique_ptr<cpp_expression> expr)
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `decltype` type.
|
||||
static std::unique_ptr<cpp_decltype_type> build(std::unique_ptr<cpp_expression> expr)
|
||||
{
|
||||
return std::unique_ptr<cpp_decltype_type>(new cpp_decltype_type(std::move(expr)));
|
||||
}
|
||||
return std::unique_ptr<cpp_decltype_type>(new cpp_decltype_type(std::move(expr)));
|
||||
}
|
||||
|
||||
/// \returns A reference to the expression given.
|
||||
const cpp_expression& expression() const noexcept
|
||||
{
|
||||
return *expr_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_decltype_type(std::unique_ptr<cpp_expression> expr) : expr_(std::move(expr)) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::decltype_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_expression> expr_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that isn't given but deduced using the `decltype` rules.
|
||||
class cpp_decltype_auto_type final : public cpp_type
|
||||
/// \returns A reference to the expression given.
|
||||
const cpp_expression& expression() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `auto` type.
|
||||
static std::unique_ptr<cpp_decltype_auto_type> build()
|
||||
{
|
||||
return std::unique_ptr<cpp_decltype_auto_type>(new cpp_decltype_auto_type);
|
||||
}
|
||||
return *expr_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_decltype_auto_type() = default;
|
||||
private:
|
||||
cpp_decltype_type(std::unique_ptr<cpp_expression> expr) : expr_(std::move(expr)) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::decltype_auto_t;
|
||||
}
|
||||
};
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::decltype_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_expression> expr_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that isn't given but deduced using the `decltype` rules.
|
||||
class cpp_decltype_auto_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `auto` type.
|
||||
static std::unique_ptr<cpp_decltype_auto_type> build()
|
||||
{
|
||||
return std::unique_ptr<cpp_decltype_auto_type>(new cpp_decltype_auto_type);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_decltype_auto_type() = default;
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::decltype_auto_t;
|
||||
}
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,229 +10,227 @@
|
|||
|
||||
#include <type_safe/optional_ref.hpp>
|
||||
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
#include <cppast/cpp_attribute.hpp>
|
||||
#include <cppast/cpp_token.hpp>
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_entity;
|
||||
enum class cpp_entity_kind;
|
||||
class cpp_entity_index;
|
||||
struct cpp_entity_id;
|
||||
class cpp_template_parameter;
|
||||
class cpp_template;
|
||||
class cpp_entity;
|
||||
enum class cpp_entity_kind;
|
||||
class cpp_entity_index;
|
||||
struct cpp_entity_id;
|
||||
class cpp_template_parameter;
|
||||
class cpp_template;
|
||||
|
||||
/// The name of a scope.
|
||||
/// The name of a scope.
|
||||
///
|
||||
/// It is a combination of a name and optional template parameters.
|
||||
class cpp_scope_name
|
||||
{
|
||||
public:
|
||||
/// \effects Creates a scope out of a given entity.
|
||||
cpp_scope_name(type_safe::object_ref<const cpp_entity> entity);
|
||||
|
||||
/// \returns The name of the scope.
|
||||
const std::string& name() const noexcept;
|
||||
|
||||
/// \returns Whether or not the scope is templated.
|
||||
bool is_templated() const noexcept
|
||||
{
|
||||
return templ_.has_value();
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities
|
||||
/// of the scope. \requires The scope is templated.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> template_parameters() const noexcept;
|
||||
|
||||
private:
|
||||
type_safe::object_ref<const cpp_entity> entity_;
|
||||
type_safe::optional_ref<const cpp_template> templ_;
|
||||
};
|
||||
|
||||
/// The base class for all entities in the C++ AST.
|
||||
class cpp_entity : detail::intrusive_list_node<cpp_entity>
|
||||
{
|
||||
public:
|
||||
cpp_entity(const cpp_entity&) = delete;
|
||||
cpp_entity& operator=(const cpp_entity&) = delete;
|
||||
|
||||
virtual ~cpp_entity() noexcept = default;
|
||||
|
||||
/// \returns The kind of the entity.
|
||||
cpp_entity_kind kind() const noexcept
|
||||
{
|
||||
return do_get_entity_kind();
|
||||
}
|
||||
|
||||
/// \returns The name of the entity.
|
||||
/// The name is the string associated with the entity's declaration.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns The name of the new scope created by the entity,
|
||||
/// if there is any.
|
||||
type_safe::optional<cpp_scope_name> scope_name() const
|
||||
{
|
||||
return do_get_scope_name();
|
||||
}
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the parent entity in the AST.
|
||||
type_safe::optional_ref<const cpp_entity> parent() const noexcept
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
/// \returns The documentation comment associated with that entity, if any.
|
||||
/// \notes A documentation comment can have three forms:
|
||||
///
|
||||
/// It is a combination of a name and optional template parameters.
|
||||
class cpp_scope_name
|
||||
{
|
||||
public:
|
||||
/// \effects Creates a scope out of a given entity.
|
||||
cpp_scope_name(type_safe::object_ref<const cpp_entity> entity);
|
||||
|
||||
/// \returns The name of the scope.
|
||||
const std::string& name() const noexcept;
|
||||
|
||||
/// \returns Whether or not the scope is templated.
|
||||
bool is_templated() const noexcept
|
||||
{
|
||||
return templ_.has_value();
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities of the scope.
|
||||
/// \requires The scope is templated.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> template_parameters() const
|
||||
noexcept;
|
||||
|
||||
private:
|
||||
type_safe::object_ref<const cpp_entity> entity_;
|
||||
type_safe::optional_ref<const cpp_template> templ_;
|
||||
};
|
||||
|
||||
/// The base class for all entities in the C++ AST.
|
||||
class cpp_entity : detail::intrusive_list_node<cpp_entity>
|
||||
{
|
||||
public:
|
||||
cpp_entity(const cpp_entity&) = delete;
|
||||
cpp_entity& operator=(const cpp_entity&) = delete;
|
||||
|
||||
virtual ~cpp_entity() noexcept = default;
|
||||
|
||||
/// \returns The kind of the entity.
|
||||
cpp_entity_kind kind() const noexcept
|
||||
{
|
||||
return do_get_entity_kind();
|
||||
}
|
||||
|
||||
/// \returns The name of the entity.
|
||||
/// The name is the string associated with the entity's declaration.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns The name of the new scope created by the entity,
|
||||
/// if there is any.
|
||||
type_safe::optional<cpp_scope_name> scope_name() const
|
||||
{
|
||||
return do_get_scope_name();
|
||||
}
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the parent entity in the AST.
|
||||
type_safe::optional_ref<const cpp_entity> parent() const noexcept
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
/// \returns The documentation comment associated with that entity, if any.
|
||||
/// \notes A documentation comment can have three forms:
|
||||
///
|
||||
/// * A C style doc comment. It is a C style comment starting with an additional `*`, i.e. `/**`.
|
||||
/// One space after the leading sequence will be skipped.
|
||||
/// It ends either with `*/` or `**/`.
|
||||
/// After a newline all whitespace is skipped, as well as an optional `*` followed by another optional space,
|
||||
/// as well as trailing whitespace on each line.
|
||||
/// I.e. `/** a\n * b */` yields the text `a\nb`.
|
||||
/// * A C++ style doc comment. It is a C++ style comment starting with an additional `/` or '!`,
|
||||
/// i.e. `///` or `//!`.
|
||||
/// One space character after the leading sequence will be skipped,
|
||||
/// as well as any trailing whitespace.
|
||||
/// Two C++ style doc comments on two adjacent lines will be merged.
|
||||
/// * An end of line doc comment. It is a C++ style comment starting with an '<', i.e. `//<`.
|
||||
/// One space character after the leading sequence will be skipped,
|
||||
/// as well as any trailing whitespace.
|
||||
/// If the next line is a C++ style doc comment, it will be merged with that one.
|
||||
///
|
||||
/// A documentation comment is associated with an entity,
|
||||
/// if for C and C++ style doc comments, the entity declaration begins
|
||||
/// on the line after the last line of the comment,
|
||||
/// and if for an end of line comment, the entity declaration ends
|
||||
/// on the same line as the end of line comment.
|
||||
///
|
||||
/// This comment system is also used by [standardese](https://standardese.foonathan.net).
|
||||
type_safe::optional_ref<const std::string> comment() const noexcept
|
||||
{
|
||||
return comment_.empty() ? nullptr : type_safe::opt_ref(&comment_);
|
||||
}
|
||||
|
||||
/// \effects Sets the associated comment.
|
||||
/// \requires The comment must not be empty, if there is one.
|
||||
void set_comment(type_safe::optional<std::string> comment) noexcept
|
||||
{
|
||||
comment_ = comment.value_or("");
|
||||
}
|
||||
|
||||
/// \returns The list of attributes that are specified for that entity.
|
||||
const cpp_attribute_list& attributes() const noexcept
|
||||
{
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
/// \effects Adds an attribute for that entity.
|
||||
void add_attribute(cpp_attribute attr) noexcept
|
||||
{
|
||||
attributes_.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
/// \effects Adds multiple arguments for that entity.
|
||||
void add_attribute(const cpp_attribute_list& list) noexcept
|
||||
{
|
||||
attributes_.insert(attributes_.end(), list.begin(), list.end());
|
||||
}
|
||||
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Creates it giving it the the name.
|
||||
cpp_entity(std::string name) : name_(std::move(name)), user_data_(nullptr) {}
|
||||
|
||||
private:
|
||||
/// \returns The kind of the entity.
|
||||
virtual cpp_entity_kind do_get_entity_kind() const noexcept = 0;
|
||||
|
||||
/// \returns The name of the new scope created by the entity, if any.
|
||||
/// By default, there is no scope created.
|
||||
virtual type_safe::optional<cpp_scope_name> do_get_scope_name() const
|
||||
{
|
||||
return type_safe::nullopt;
|
||||
}
|
||||
|
||||
void on_insert(const cpp_entity& parent) noexcept
|
||||
{
|
||||
parent_ = type_safe::ref(parent);
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
std::string comment_;
|
||||
cpp_attribute_list attributes_;
|
||||
type_safe::optional_ref<const cpp_entity> parent_;
|
||||
mutable std::atomic<void*> user_data_;
|
||||
|
||||
template <typename T>
|
||||
friend struct detail::intrusive_list_access;
|
||||
friend detail::intrusive_list_node<cpp_entity>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() that isn't exposed directly.
|
||||
/// * A C style doc comment. It is a C style comment starting with an additional `*`, i.e.
|
||||
/// `/**`. One space after the leading sequence will be skipped. It ends either with `*/` or
|
||||
/// `**/`. After a newline all whitespace is skipped, as well as an optional `*` followed by
|
||||
/// another optional space, as well as trailing whitespace on each line. I.e. `/** a\n * b
|
||||
/// */` yields the text `a\nb`.
|
||||
/// * A C++ style doc comment. It is a C++ style comment starting with an additional `/` or '!`,
|
||||
/// i.e. `///` or `//!`.
|
||||
/// One space character after the leading sequence will be skipped,
|
||||
/// as well as any trailing whitespace.
|
||||
/// Two C++ style doc comments on two adjacent lines will be merged.
|
||||
/// * An end of line doc comment. It is a C++ style comment starting with an '<', i.e. `//<`.
|
||||
/// One space character after the leading sequence will be skipped,
|
||||
/// as well as any trailing whitespace.
|
||||
/// If the next line is a C++ style doc comment, it will be merged with that one.
|
||||
///
|
||||
/// The only information available is the raw source code.
|
||||
class cpp_unexposed_entity final : public cpp_entity
|
||||
/// A documentation comment is associated with an entity,
|
||||
/// if for C and C++ style doc comments, the entity declaration begins
|
||||
/// on the line after the last line of the comment,
|
||||
/// and if for an end of line comment, the entity declaration ends
|
||||
/// on the same line as the end of line comment.
|
||||
///
|
||||
/// This comment system is also used by [standardese](https://standardese.foonathan.net).
|
||||
type_safe::optional_ref<const std::string> comment() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return comment_.empty() ? nullptr : type_safe::opt_ref(&comment_);
|
||||
}
|
||||
|
||||
/// \returns A newly built and registered unexposed entity.
|
||||
/// \notes It will be registered as a declaration.
|
||||
static std::unique_ptr<cpp_entity> build(const cpp_entity_index& index, cpp_entity_id id,
|
||||
std::string name, cpp_token_string spelling);
|
||||
/// \effects Sets the associated comment.
|
||||
/// \requires The comment must not be empty, if there is one.
|
||||
void set_comment(type_safe::optional<std::string> comment) noexcept
|
||||
{
|
||||
comment_ = comment.value_or("");
|
||||
}
|
||||
|
||||
/// \returns A newly built unnamed unexposed entity.
|
||||
/// It will not be registered.
|
||||
static std::unique_ptr<cpp_entity> build(cpp_token_string spelling);
|
||||
/// \returns The list of attributes that are specified for that entity.
|
||||
const cpp_attribute_list& attributes() const noexcept
|
||||
{
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
/// \returns The spelling of that entity.
|
||||
const cpp_token_string& spelling() const noexcept
|
||||
{
|
||||
return spelling_;
|
||||
}
|
||||
/// \effects Adds an attribute for that entity.
|
||||
void add_attribute(cpp_attribute attr) noexcept
|
||||
{
|
||||
attributes_.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_unexposed_entity(std::string name, cpp_token_string spelling)
|
||||
: cpp_entity(std::move(name)), spelling_(std::move(spelling))
|
||||
{
|
||||
}
|
||||
/// \effects Adds multiple arguments for that entity.
|
||||
void add_attribute(const cpp_attribute_list& list) noexcept
|
||||
{
|
||||
attributes_.insert(attributes_.end(), list.begin(), list.end());
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
cpp_token_string spelling_;
|
||||
};
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to
|
||||
/// maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the entity is templated.
|
||||
/// If this function returns `true` that means the entity is not the "real" entity,
|
||||
/// but contains just the information for the template which is the parent entity.
|
||||
/// \notes Do not use this entity other to read information from the template entity.
|
||||
bool is_templated(const cpp_entity& e) noexcept;
|
||||
protected:
|
||||
/// \effects Creates it giving it the the name.
|
||||
cpp_entity(std::string name) : name_(std::move(name)), user_data_(nullptr) {}
|
||||
|
||||
/// \returns Whether or not the given entity is "friended",
|
||||
/// that is, its declaration exists as part of a [cppast::cpp_friend]() declaration.
|
||||
bool is_friended(const cpp_entity& e) noexcept;
|
||||
private:
|
||||
/// \returns The kind of the entity.
|
||||
virtual cpp_entity_kind do_get_entity_kind() const noexcept = 0;
|
||||
|
||||
/// \returns The name of the new scope created by the entity, if any.
|
||||
/// By default, there is no scope created.
|
||||
virtual type_safe::optional<cpp_scope_name> do_get_scope_name() const
|
||||
{
|
||||
return type_safe::nullopt;
|
||||
}
|
||||
|
||||
void on_insert(const cpp_entity& parent) noexcept
|
||||
{
|
||||
parent_ = type_safe::ref(parent);
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
std::string comment_;
|
||||
cpp_attribute_list attributes_;
|
||||
type_safe::optional_ref<const cpp_entity> parent_;
|
||||
mutable std::atomic<void*> user_data_;
|
||||
|
||||
template <typename T>
|
||||
friend struct detail::intrusive_list_access;
|
||||
friend detail::intrusive_list_node<cpp_entity>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() that isn't exposed directly.
|
||||
///
|
||||
/// The only information available is the raw source code.
|
||||
class cpp_unexposed_entity final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly built and registered unexposed entity.
|
||||
/// \notes It will be registered as a declaration.
|
||||
static std::unique_ptr<cpp_entity> build(const cpp_entity_index& index, cpp_entity_id id,
|
||||
std::string name, cpp_token_string spelling);
|
||||
|
||||
/// \returns A newly built unnamed unexposed entity.
|
||||
/// It will not be registered.
|
||||
static std::unique_ptr<cpp_entity> build(cpp_token_string spelling);
|
||||
|
||||
/// \returns The spelling of that entity.
|
||||
const cpp_token_string& spelling() const noexcept
|
||||
{
|
||||
return spelling_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_unexposed_entity(std::string name, cpp_token_string spelling)
|
||||
: cpp_entity(std::move(name)), spelling_(std::move(spelling))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_token_string spelling_;
|
||||
};
|
||||
|
||||
/// \returns Whether or not the entity is templated.
|
||||
/// If this function returns `true` that means the entity is not the "real" entity,
|
||||
/// but contains just the information for the template which is the parent entity.
|
||||
/// \notes Do not use this entity other to read information from the template entity.
|
||||
bool is_templated(const cpp_entity& e) noexcept;
|
||||
|
||||
/// \returns Whether or not the given entity is "friended",
|
||||
/// that is, its declaration exists as part of a [cppast::cpp_friend]() declaration.
|
||||
bool is_friended(const cpp_entity& e) noexcept;
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENTITY_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -9,51 +9,51 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Helper class for entities that are containers.
|
||||
///
|
||||
/// Inherit from it to generate container access.
|
||||
template <class Derived, typename T>
|
||||
class cpp_entity_container
|
||||
/// Helper class for entities that are containers.
|
||||
///
|
||||
/// Inherit from it to generate container access.
|
||||
template <class Derived, typename T>
|
||||
class cpp_entity_container
|
||||
{
|
||||
public:
|
||||
using iterator = typename detail::intrusive_list<T>::const_iterator;
|
||||
|
||||
/// \returns A const iterator to the first child.
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
public:
|
||||
using iterator = typename detail::intrusive_list<T>::const_iterator;
|
||||
return children_.begin();
|
||||
}
|
||||
|
||||
/// \returns A const iterator to the first child.
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return children_.begin();
|
||||
}
|
||||
/// \returns A const iterator to the last child.
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return children_.end();
|
||||
}
|
||||
|
||||
/// \returns A const iterator to the last child.
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return children_.end();
|
||||
}
|
||||
protected:
|
||||
/// \effects Adds a new child to the container.
|
||||
void add_child(std::unique_ptr<T> ptr) noexcept
|
||||
{
|
||||
children_.push_back(static_cast<Derived&>(*this), std::move(ptr));
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Adds a new child to the container.
|
||||
void add_child(std::unique_ptr<T> ptr) noexcept
|
||||
{
|
||||
children_.push_back(static_cast<Derived&>(*this), std::move(ptr));
|
||||
}
|
||||
/// \returns A non-const iterator to the first child.
|
||||
typename detail::intrusive_list<T>::iterator mutable_begin() noexcept
|
||||
{
|
||||
return children_.begin();
|
||||
}
|
||||
|
||||
/// \returns A non-const iterator to the first child.
|
||||
typename detail::intrusive_list<T>::iterator mutable_begin() noexcept
|
||||
{
|
||||
return children_.begin();
|
||||
}
|
||||
/// \returns A non-const iterator one past the last child.
|
||||
typename detail::intrusive_list<T>::iterator mutable_end() noexcept
|
||||
{
|
||||
return children_.begin();
|
||||
}
|
||||
|
||||
/// \returns A non-const iterator one past the last child.
|
||||
typename detail::intrusive_list<T>::iterator mutable_end() noexcept
|
||||
{
|
||||
return children_.begin();
|
||||
}
|
||||
~cpp_entity_container() noexcept = default;
|
||||
|
||||
~cpp_entity_container() noexcept = default;
|
||||
|
||||
private:
|
||||
detail::intrusive_list<T> children_;
|
||||
};
|
||||
private:
|
||||
detail::intrusive_list<T> children_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -16,130 +16,128 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_entity;
|
||||
class cpp_file;
|
||||
class cpp_namespace;
|
||||
class cpp_entity;
|
||||
class cpp_file;
|
||||
class cpp_namespace;
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
constexpr std::size_t fnv_basis = 14695981039346656037ull;
|
||||
constexpr std::size_t fnv_prime = 1099511628211ull;
|
||||
|
||||
// FNV-1a 64 bit hash
|
||||
constexpr std::size_t id_hash(const char* str, std::size_t hash = fnv_basis)
|
||||
{
|
||||
constexpr std::size_t fnv_basis = 14695981039346656037ull;
|
||||
constexpr std::size_t fnv_prime = 1099511628211ull;
|
||||
|
||||
// FNV-1a 64 bit hash
|
||||
constexpr std::size_t id_hash(const char* str, std::size_t hash = fnv_basis)
|
||||
{
|
||||
return *str ? id_hash(str + 1, (hash ^ std::size_t(*str)) * fnv_prime) : hash;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity]().
|
||||
///
|
||||
/// It is comparable for equality.
|
||||
struct cpp_entity_id : type_safe::strong_typedef<cpp_entity_id, std::size_t>,
|
||||
type_safe::strong_typedef_op::equality_comparison<cpp_entity_id>
|
||||
{
|
||||
explicit cpp_entity_id(const std::string& str) : cpp_entity_id(str.c_str()) {}
|
||||
|
||||
explicit cpp_entity_id(const char* str) : strong_typedef(detail::id_hash(str)) {}
|
||||
};
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
/// \returns A new [cppast::cpp_entity_id]() created from the given string.
|
||||
inline cpp_entity_id operator"" _id(const char* str, std::size_t)
|
||||
{
|
||||
return cpp_entity_id(str);
|
||||
}
|
||||
return *str ? id_hash(str + 1, (hash ^ std::size_t(*str)) * fnv_prime) : hash;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// An index of all [cppast::cpp_entity]() objects created.
|
||||
///
|
||||
/// It maps [cppast::cpp_entity_id]() to references to the [cppast::cpp_entity]() objects.
|
||||
class cpp_entity_index
|
||||
/// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity]().
|
||||
///
|
||||
/// It is comparable for equality.
|
||||
struct cpp_entity_id : type_safe::strong_typedef<cpp_entity_id, std::size_t>,
|
||||
type_safe::strong_typedef_op::equality_comparison<cpp_entity_id>
|
||||
{
|
||||
explicit cpp_entity_id(const std::string& str) : cpp_entity_id(str.c_str()) {}
|
||||
|
||||
explicit cpp_entity_id(const char* str) : strong_typedef(detail::id_hash(str)) {}
|
||||
};
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
/// \returns A new [cppast::cpp_entity_id]() created from the given string.
|
||||
inline cpp_entity_id operator"" _id(const char* str, std::size_t)
|
||||
{
|
||||
return cpp_entity_id(str);
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
/// An index of all [cppast::cpp_entity]() objects created.
|
||||
///
|
||||
/// It maps [cppast::cpp_entity_id]() to references to the [cppast::cpp_entity]() objects.
|
||||
class cpp_entity_index
|
||||
{
|
||||
public:
|
||||
/// Exception thrown on duplicate entity definition.
|
||||
class duplicate_definition_error : public std::logic_error
|
||||
{
|
||||
public:
|
||||
/// Exception thrown on duplicate entity definition.
|
||||
class duplicate_definition_error : public std::logic_error
|
||||
{
|
||||
public:
|
||||
duplicate_definition_error();
|
||||
};
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_entity]() which is a definition.
|
||||
/// It will override any previously registered declarations of the same entity.
|
||||
/// \throws duplicate_defintion_error if the entity has been registered as definition before.
|
||||
/// \requires The entity must live as long as the index lives,
|
||||
/// and it must not be a namespace.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_definition(cpp_entity_id id,
|
||||
type_safe::object_ref<const cpp_entity> entity) const;
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_file]().
|
||||
/// \returns `true` if the file was not registered before.
|
||||
/// If it returns `false`, the file was registered before and nothing was changed.
|
||||
/// \requires The entity must live as long as the index lives.
|
||||
/// \notes This operation is thread safe.
|
||||
bool register_file(cpp_entity_id id, type_safe::object_ref<const cpp_file> file) const;
|
||||
|
||||
/// \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.
|
||||
/// \requires The entity must be forward declarable.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_forward_declaration(cpp_entity_id id,
|
||||
type_safe::object_ref<const cpp_entity> entity) const;
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_namespace]().
|
||||
/// \notes The namespace object must live as long as the index lives.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_namespace(cpp_entity_id id,
|
||||
type_safe::object_ref<const cpp_namespace> ns) const;
|
||||
|
||||
/// \returns A [ts::optional_ref]() corresponding to the entity(/ies) of the given [cppast::cpp_entity_id]().
|
||||
/// If no definition has been registered, it return the first declaration that was registered.
|
||||
/// If the id resolves to a namespaces, returns an empty optional.
|
||||
/// \notes This operation is thread safe.
|
||||
type_safe::optional_ref<const cpp_entity> lookup(const cpp_entity_id& id) const noexcept;
|
||||
|
||||
/// \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<const cpp_entity> lookup_definition(const cpp_entity_id& id) const
|
||||
noexcept;
|
||||
|
||||
/// \returns A [ts::array_ref]() of references to all namespaces matching the given [cppast::cpp_entity_id]().
|
||||
/// If no namespace is found, it returns an empty array reference.
|
||||
/// \notes This operation is thread safe.
|
||||
auto lookup_namespace(const cpp_entity_id& id) const noexcept
|
||||
-> type_safe::array_ref<type_safe::object_ref<const cpp_namespace>>;
|
||||
|
||||
private:
|
||||
struct hash
|
||||
{
|
||||
std::size_t operator()(const cpp_entity_id& id) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(id);
|
||||
}
|
||||
};
|
||||
|
||||
struct value
|
||||
{
|
||||
type_safe::object_ref<const cpp_entity> entity;
|
||||
bool is_definition;
|
||||
|
||||
value(type_safe::object_ref<const cpp_entity> e, bool def)
|
||||
: entity(std::move(e)), is_definition(def)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
mutable std::unordered_map<cpp_entity_id, value, hash> map_;
|
||||
mutable std::unordered_map<cpp_entity_id,
|
||||
std::vector<type_safe::object_ref<const cpp_namespace>>, hash>
|
||||
ns_;
|
||||
duplicate_definition_error();
|
||||
};
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_entity]() which is a definition.
|
||||
/// It will override any previously registered declarations of the same entity.
|
||||
/// \throws duplicate_defintion_error if the entity has been registered as definition before.
|
||||
/// \requires The entity must live as long as the index lives,
|
||||
/// and it must not be a namespace.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_definition(cpp_entity_id id,
|
||||
type_safe::object_ref<const cpp_entity> entity) const;
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_file]().
|
||||
/// \returns `true` if the file was not registered before.
|
||||
/// If it returns `false`, the file was registered before and nothing was changed.
|
||||
/// \requires The entity must live as long as the index lives.
|
||||
/// \notes This operation is thread safe.
|
||||
bool register_file(cpp_entity_id id, type_safe::object_ref<const cpp_file> file) const;
|
||||
|
||||
/// \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.
|
||||
/// \requires The entity must be forward declarable.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_forward_declaration(cpp_entity_id id,
|
||||
type_safe::object_ref<const cpp_entity> entity) const;
|
||||
|
||||
/// \effects Registers a new [cppast::cpp_namespace]().
|
||||
/// \notes The namespace object must live as long as the index lives.
|
||||
/// \notes This operation is thread safe.
|
||||
void register_namespace(cpp_entity_id id, type_safe::object_ref<const cpp_namespace> ns) const;
|
||||
|
||||
/// \returns A [ts::optional_ref]() corresponding to the entity(/ies) of the given
|
||||
/// [cppast::cpp_entity_id](). If no definition has been registered, it return the first
|
||||
/// declaration that was registered. If the id resolves to a namespaces, returns an empty
|
||||
/// optional. \notes This operation is thread safe.
|
||||
type_safe::optional_ref<const cpp_entity> lookup(const cpp_entity_id& id) const noexcept;
|
||||
|
||||
/// \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<const cpp_entity> lookup_definition(const cpp_entity_id& id) const
|
||||
noexcept;
|
||||
|
||||
/// \returns A [ts::array_ref]() of references to all namespaces matching the given
|
||||
/// [cppast::cpp_entity_id](). If no namespace is found, it returns an empty array reference.
|
||||
/// \notes This operation is thread safe.
|
||||
auto lookup_namespace(const cpp_entity_id& id) const noexcept
|
||||
-> type_safe::array_ref<type_safe::object_ref<const cpp_namespace>>;
|
||||
|
||||
private:
|
||||
struct hash
|
||||
{
|
||||
std::size_t operator()(const cpp_entity_id& id) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(id);
|
||||
}
|
||||
};
|
||||
|
||||
struct value
|
||||
{
|
||||
type_safe::object_ref<const cpp_entity> entity;
|
||||
bool is_definition;
|
||||
|
||||
value(type_safe::object_ref<const cpp_entity> e, bool def)
|
||||
: entity(std::move(e)), is_definition(def)
|
||||
{}
|
||||
};
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
mutable std::unordered_map<cpp_entity_id, value, hash> map_;
|
||||
mutable std::unordered_map<cpp_entity_id,
|
||||
std::vector<type_safe::object_ref<const cpp_namespace>>, hash>
|
||||
ns_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -9,81 +9,81 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// All possible kinds of C++ entities.
|
||||
enum class cpp_entity_kind
|
||||
{
|
||||
file_t,
|
||||
/// All possible kinds of C++ entities.
|
||||
enum class cpp_entity_kind
|
||||
{
|
||||
file_t,
|
||||
|
||||
macro_parameter_t,
|
||||
macro_definition_t,
|
||||
include_directive_t,
|
||||
macro_parameter_t,
|
||||
macro_definition_t,
|
||||
include_directive_t,
|
||||
|
||||
language_linkage_t,
|
||||
language_linkage_t,
|
||||
|
||||
namespace_t,
|
||||
namespace_alias_t,
|
||||
using_directive_t,
|
||||
using_declaration_t,
|
||||
namespace_t,
|
||||
namespace_alias_t,
|
||||
using_directive_t,
|
||||
using_declaration_t,
|
||||
|
||||
type_alias_t,
|
||||
type_alias_t,
|
||||
|
||||
enum_t,
|
||||
enum_value_t,
|
||||
enum_t,
|
||||
enum_value_t,
|
||||
|
||||
class_t,
|
||||
access_specifier_t,
|
||||
base_class_t,
|
||||
class_t,
|
||||
access_specifier_t,
|
||||
base_class_t,
|
||||
|
||||
variable_t,
|
||||
member_variable_t,
|
||||
bitfield_t,
|
||||
variable_t,
|
||||
member_variable_t,
|
||||
bitfield_t,
|
||||
|
||||
function_parameter_t,
|
||||
function_t,
|
||||
member_function_t,
|
||||
conversion_op_t,
|
||||
constructor_t,
|
||||
destructor_t,
|
||||
function_parameter_t,
|
||||
function_t,
|
||||
member_function_t,
|
||||
conversion_op_t,
|
||||
constructor_t,
|
||||
destructor_t,
|
||||
|
||||
friend_t,
|
||||
friend_t,
|
||||
|
||||
template_type_parameter_t,
|
||||
non_type_template_parameter_t,
|
||||
template_template_parameter_t,
|
||||
template_type_parameter_t,
|
||||
non_type_template_parameter_t,
|
||||
template_template_parameter_t,
|
||||
|
||||
alias_template_t,
|
||||
variable_template_t,
|
||||
function_template_t,
|
||||
function_template_specialization_t,
|
||||
class_template_t,
|
||||
class_template_specialization_t,
|
||||
alias_template_t,
|
||||
variable_template_t,
|
||||
function_template_t,
|
||||
function_template_specialization_t,
|
||||
class_template_t,
|
||||
class_template_specialization_t,
|
||||
|
||||
static_assert_t,
|
||||
static_assert_t,
|
||||
|
||||
unexposed_t,
|
||||
unexposed_t,
|
||||
|
||||
count,
|
||||
};
|
||||
count,
|
||||
};
|
||||
|
||||
/// \returns A human readable string describing the entity kind.
|
||||
const char* to_string(cpp_entity_kind kind) noexcept;
|
||||
/// \returns A human readable string describing the entity kind.
|
||||
const char* to_string(cpp_entity_kind kind) noexcept;
|
||||
|
||||
/// \returns Whether or not a given entity kind is a C++ function,
|
||||
/// that is, it dervies from [cppast::cpp_function_base]().
|
||||
bool is_function(cpp_entity_kind kind) noexcept;
|
||||
/// \returns Whether or not a given entity kind is a C++ function,
|
||||
/// that is, it dervies from [cppast::cpp_function_base]().
|
||||
bool is_function(cpp_entity_kind kind) noexcept;
|
||||
|
||||
/// \returns Whether or not a given entity kind is a C++ (template) parameter.
|
||||
bool is_parameter(cpp_entity_kind kind) noexcept;
|
||||
/// \returns Whether or not a given entity kind is a C++ (template) parameter.
|
||||
bool is_parameter(cpp_entity_kind kind) noexcept;
|
||||
|
||||
/// \returns Whether or not a given entity kind is a C++ template,
|
||||
/// that is, it dervies from [cppast::cpp_template]().
|
||||
/// \notes A template template parameter is not considered a template for this function.
|
||||
/// \notes Template specializations are also considered templates here.
|
||||
bool is_template(cpp_entity_kind kind) noexcept;
|
||||
/// \returns Whether or not a given entity kind is a C++ template,
|
||||
/// that is, it dervies from [cppast::cpp_template]().
|
||||
/// \notes A template template parameter is not considered a template for this function.
|
||||
/// \notes Template specializations are also considered templates here.
|
||||
bool is_template(cpp_entity_kind kind) noexcept;
|
||||
|
||||
/// \returns Whether or not a given entity kind is a specialization of a C++ template,
|
||||
/// that is, it derives from [cppast::cpp_template_specialization]().
|
||||
bool is_template_specialization(cpp_entity_kind kind) noexcept;
|
||||
/// \returns Whether or not a given entity kind is a specialization of a C++ template,
|
||||
/// that is, it derives from [cppast::cpp_template_specialization]().
|
||||
bool is_template_specialization(cpp_entity_kind kind) noexcept;
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -9,123 +9,121 @@
|
|||
|
||||
#include <type_safe/variant.hpp>
|
||||
|
||||
#include <cppast/detail/assert.hpp>
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/detail/assert.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
enum class cpp_entity_kind;
|
||||
enum class cpp_entity_kind;
|
||||
|
||||
/// A basic reference to some kind of [cppast::cpp_entity]().
|
||||
///
|
||||
/// It can either refer to a single [cppast::cpp_entity]()
|
||||
/// or multiple.
|
||||
/// In the later case it is *overloaded*.
|
||||
template <typename T, typename Predicate>
|
||||
class basic_cpp_entity_ref
|
||||
/// A basic reference to some kind of [cppast::cpp_entity]().
|
||||
///
|
||||
/// It can either refer to a single [cppast::cpp_entity]()
|
||||
/// or multiple.
|
||||
/// In the later case it is *overloaded*.
|
||||
template <typename T, typename Predicate>
|
||||
class basic_cpp_entity_ref
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it giving it the target id and name.
|
||||
basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name)
|
||||
: target_(std::move(target_id)), name_(std::move(target_name))
|
||||
{}
|
||||
|
||||
/// \effects Creates it giving it multiple target ids and name.
|
||||
/// \notes This is to refer to an overloaded function.
|
||||
basic_cpp_entity_ref(std::vector<cpp_entity_id> target_ids, std::string target_name)
|
||||
: target_(std::move(target_ids)), name_(std::move(target_name))
|
||||
{}
|
||||
|
||||
/// \returns The name of the reference, as spelled in the source code.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it giving it the target id and name.
|
||||
basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name)
|
||||
: target_(std::move(target_id)), name_(std::move(target_name))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Creates it giving it multiple target ids and name.
|
||||
/// \notes This is to refer to an overloaded function.
|
||||
basic_cpp_entity_ref(std::vector<cpp_entity_id> target_ids, std::string target_name)
|
||||
: target_(std::move(target_ids)), name_(std::move(target_name))
|
||||
{
|
||||
}
|
||||
|
||||
/// \returns The name of the reference, as spelled in the source code.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it refers to multiple entities.
|
||||
bool is_overloaded() const noexcept
|
||||
{
|
||||
return target_.has_value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
}
|
||||
|
||||
/// \returns The number of entities it refers to.
|
||||
type_safe::size_t no_overloaded() const noexcept
|
||||
{
|
||||
return id().size();
|
||||
}
|
||||
|
||||
/// \returns An array reference to the id or ids it refers to.
|
||||
type_safe::array_ref<const cpp_entity_id> id() const noexcept
|
||||
{
|
||||
if (is_overloaded())
|
||||
{
|
||||
auto& vec = target_.value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& id = target_.value(type_safe::variant_type<cpp_entity_id>{});
|
||||
return type_safe::ref(&id, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns An array reference to the entities it refers to.
|
||||
/// The return type provides `operator[]` + `size()`,
|
||||
/// as well as `begin()` and `end()` returning forward iterators.
|
||||
/// \exclude return
|
||||
std::vector<type_safe::object_ref<const T>> get(const cpp_entity_index& idx) const
|
||||
{
|
||||
std::vector<type_safe::object_ref<const T>> result;
|
||||
get_impl(std::is_convertible<cpp_namespace&, T&>{}, result, idx);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(std::true_type, std::vector<type_safe::object_ref<const T>>& result,
|
||||
const cpp_entity_index& idx) const
|
||||
{
|
||||
for (auto& cur : id())
|
||||
for (auto& ns : idx.lookup_namespace(cur))
|
||||
result.push_back(ns);
|
||||
if (!std::is_same<T, cpp_namespace>::value)
|
||||
get_impl(std::false_type{}, result, idx);
|
||||
}
|
||||
|
||||
void get_impl(std::false_type, std::vector<type_safe::object_ref<const T>>& result,
|
||||
const cpp_entity_index& idx) const
|
||||
{
|
||||
for (auto& cur : id())
|
||||
{
|
||||
auto entity = idx.lookup(cur).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(Predicate{}(e), detail::precondition_error_handler{},
|
||||
"invalid entity type");
|
||||
return type_safe::ref(static_cast<const T&>(e));
|
||||
});
|
||||
if (entity)
|
||||
result.push_back(type_safe::ref(entity.value()));
|
||||
}
|
||||
}
|
||||
|
||||
type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_entity_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// A [cppast::basic_cpp_entity_ref]() to any [cppast::cpp_entity]().
|
||||
using cpp_entity_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_entity_ref_predicate>;
|
||||
/// \returns Whether or not it refers to multiple entities.
|
||||
bool is_overloaded() const noexcept
|
||||
{
|
||||
return target_.has_value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
}
|
||||
|
||||
/// \returns The number of entities it refers to.
|
||||
type_safe::size_t no_overloaded() const noexcept
|
||||
{
|
||||
return id().size();
|
||||
}
|
||||
|
||||
/// \returns An array reference to the id or ids it refers to.
|
||||
type_safe::array_ref<const cpp_entity_id> id() const noexcept
|
||||
{
|
||||
if (is_overloaded())
|
||||
{
|
||||
auto& vec = target_.value(type_safe::variant_type<std::vector<cpp_entity_id>>{});
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& id = target_.value(type_safe::variant_type<cpp_entity_id>{});
|
||||
return type_safe::ref(&id, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns An array reference to the entities it refers to.
|
||||
/// The return type provides `operator[]` + `size()`,
|
||||
/// as well as `begin()` and `end()` returning forward iterators.
|
||||
/// \exclude return
|
||||
std::vector<type_safe::object_ref<const T>> get(const cpp_entity_index& idx) const
|
||||
{
|
||||
std::vector<type_safe::object_ref<const T>> result;
|
||||
get_impl(std::is_convertible<cpp_namespace&, T&>{}, result, idx);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(std::true_type, std::vector<type_safe::object_ref<const T>>& result,
|
||||
const cpp_entity_index& idx) const
|
||||
{
|
||||
for (auto& cur : id())
|
||||
for (auto& ns : idx.lookup_namespace(cur))
|
||||
result.push_back(ns);
|
||||
if (!std::is_same<T, cpp_namespace>::value)
|
||||
get_impl(std::false_type{}, result, idx);
|
||||
}
|
||||
|
||||
void get_impl(std::false_type, std::vector<type_safe::object_ref<const T>>& result,
|
||||
const cpp_entity_index& idx) const
|
||||
{
|
||||
for (auto& cur : id())
|
||||
{
|
||||
auto entity = idx.lookup(cur).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(Predicate{}(e), detail::precondition_error_handler{},
|
||||
"invalid entity type");
|
||||
return type_safe::ref(static_cast<const T&>(e));
|
||||
});
|
||||
if (entity)
|
||||
result.push_back(type_safe::ref(entity.value()));
|
||||
}
|
||||
}
|
||||
|
||||
type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_entity_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// A [cppast::basic_cpp_entity_ref]() to any [cppast::cpp_entity]().
|
||||
using cpp_entity_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_entity_ref_predicate>;
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -9,139 +9,132 @@
|
|||
|
||||
#include <type_safe/optional_ref.hpp>
|
||||
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_entity_container.hpp>
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_expression.hpp>
|
||||
#include <cppast/cpp_forward_declarable.hpp>
|
||||
#include <cppast/cpp_type.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling the value of an [cppast::cpp_enum]().
|
||||
class cpp_enum_value final : public cpp_entity
|
||||
/// A [cppast::cpp_entity]() modelling the value of an [cppast::cpp_enum]().
|
||||
class cpp_enum_value final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered enum value.
|
||||
/// \notes `value` may be `nullptr`, in which case the enum has an implicit value.
|
||||
static std::unique_ptr<cpp_enum_value> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name,
|
||||
std::unique_ptr<cpp_expression> value = nullptr);
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the enum value.
|
||||
/// \notes It only has an associated expression if the value is explictly given.
|
||||
type_safe::optional_ref<const cpp_expression> value() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(value_.get());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_enum_value(std::string name, std::unique_ptr<cpp_expression> value)
|
||||
: cpp_entity(std::move(name)), value_(std::move(value))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_expression> value_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ enumeration.
|
||||
///
|
||||
/// This can either be a definition or just a forward declaration.
|
||||
/// If it is just forward declared, it will not have any children.
|
||||
class cpp_enum final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_enum, cpp_enum_value>,
|
||||
public cpp_forward_declarable
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_enum]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Sets the name, underlying type and whether it is scoped.
|
||||
builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type, bool explicit_type)
|
||||
: enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped))
|
||||
{}
|
||||
|
||||
/// \returns A newly created and registered enum value.
|
||||
/// \notes `value` may be `nullptr`, in which case the enum has an implicit value.
|
||||
static std::unique_ptr<cpp_enum_value> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_expression> value = nullptr);
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the enum value.
|
||||
/// \notes It only has an associated expression if the value is explictly given.
|
||||
type_safe::optional_ref<const cpp_expression> value() const noexcept
|
||||
/// \effects Adds a [cppast::cpp_enum_value]().
|
||||
void add_value(std::unique_ptr<cpp_enum_value> value)
|
||||
{
|
||||
return type_safe::opt_cref(value_.get());
|
||||
enum_->add_child(std::move(value));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished enumeration.
|
||||
cpp_enum& get() noexcept
|
||||
{
|
||||
return *enum_;
|
||||
}
|
||||
|
||||
/// \effects Registers the enum in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished enum.
|
||||
std::unique_ptr<cpp_enum> finish(
|
||||
const cpp_entity_index& idx, cpp_entity_id id,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||
{
|
||||
enum_->set_semantic_parent(std::move(semantic_parent));
|
||||
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.
|
||||
std::unique_ptr<cpp_enum> finish_declaration(const cpp_entity_index& idx,
|
||||
cpp_entity_id definition_id) noexcept
|
||||
{
|
||||
enum_->mark_declaration(definition_id);
|
||||
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_));
|
||||
return std::move(enum_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_enum_value(std::string name, std::unique_ptr<cpp_expression> value)
|
||||
: cpp_entity(std::move(name)), value_(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_expression> value_;
|
||||
std::unique_ptr<cpp_enum> enum_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ enumeration.
|
||||
///
|
||||
/// This can either be a definition or just a forward declaration.
|
||||
/// If it is just forward declared, it will not have any children.
|
||||
class cpp_enum final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_enum, cpp_enum_value>,
|
||||
public cpp_forward_declarable
|
||||
/// \returns A reference to the underlying [cppast::cpp_type]() of the enum.
|
||||
const cpp_type& underlying_type() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// Builds a [cppast::cpp_enum]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name, underlying type and whether it is scoped.
|
||||
builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type,
|
||||
bool explicit_type)
|
||||
: enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped))
|
||||
{
|
||||
}
|
||||
/// \returns Whether or not the underlying type is explictly given.
|
||||
bool has_explicit_type() const noexcept
|
||||
{
|
||||
return type_given_;
|
||||
}
|
||||
|
||||
/// \effects Adds a [cppast::cpp_enum_value]().
|
||||
void add_value(std::unique_ptr<cpp_enum_value> value)
|
||||
{
|
||||
enum_->add_child(std::move(value));
|
||||
}
|
||||
/// \returns Whether or not it is a scoped enumeration (i.e. an `enum class`).
|
||||
bool is_scoped() const noexcept
|
||||
{
|
||||
return scoped_;
|
||||
}
|
||||
|
||||
/// \returns The not yet finished enumeration.
|
||||
cpp_enum& get() noexcept
|
||||
{
|
||||
return *enum_;
|
||||
}
|
||||
private:
|
||||
cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool type_given, bool scoped)
|
||||
: cpp_entity(std::move(name)), type_(std::move(type)), scoped_(scoped), type_given_(type_given)
|
||||
{}
|
||||
|
||||
/// \effects Registers the enum in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished enum.
|
||||
std::unique_ptr<cpp_enum> finish(
|
||||
const cpp_entity_index& idx, cpp_entity_id id,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||
{
|
||||
enum_->set_semantic_parent(std::move(semantic_parent));
|
||||
idx.register_definition(std::move(id), type_safe::ref(*enum_));
|
||||
return std::move(enum_);
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
/// \effects Marks the enum as forward declaration.
|
||||
/// \returns The finished enum.
|
||||
std::unique_ptr<cpp_enum> finish_declaration(const cpp_entity_index& idx,
|
||||
cpp_entity_id definition_id) noexcept
|
||||
{
|
||||
enum_->mark_declaration(definition_id);
|
||||
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_));
|
||||
return std::move(enum_);
|
||||
}
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_enum> enum_;
|
||||
};
|
||||
|
||||
/// \returns A reference to the underlying [cppast::cpp_type]() of the enum.
|
||||
const cpp_type& underlying_type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the underlying type is explictly given.
|
||||
bool has_explicit_type() const noexcept
|
||||
{
|
||||
return type_given_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is a scoped enumeration (i.e. an `enum class`).
|
||||
bool is_scoped() const noexcept
|
||||
{
|
||||
return scoped_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool type_given, bool scoped)
|
||||
: cpp_entity(std::move(name)),
|
||||
type_(std::move(type)),
|
||||
scoped_(scoped),
|
||||
type_given_(type_given)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
bool scoped_, type_given_;
|
||||
};
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
bool scoped_, type_given_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_ENUM_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -13,139 +13,138 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// The kind of a [cppast::cpp_expression]().
|
||||
enum class cpp_expression_kind
|
||||
/// The kind of a [cppast::cpp_expression]().
|
||||
enum class cpp_expression_kind
|
||||
{
|
||||
literal_t,
|
||||
|
||||
unexposed_t,
|
||||
};
|
||||
|
||||
/// Base class for all C++ expressions.
|
||||
class cpp_expression
|
||||
{
|
||||
public:
|
||||
cpp_expression(const cpp_expression&) = delete;
|
||||
cpp_expression& operator=(const cpp_expression&) = delete;
|
||||
|
||||
virtual ~cpp_expression() noexcept = default;
|
||||
|
||||
/// \returns The [cppast::cpp_expression_kind]().
|
||||
cpp_expression_kind kind() const noexcept
|
||||
{
|
||||
literal_t,
|
||||
return do_get_kind();
|
||||
}
|
||||
|
||||
unexposed_t,
|
||||
};
|
||||
|
||||
/// Base class for all C++ expressions.
|
||||
class cpp_expression
|
||||
/// \returns The type of the expression.
|
||||
const cpp_type& type() const noexcept
|
||||
{
|
||||
public:
|
||||
cpp_expression(const cpp_expression&) = delete;
|
||||
cpp_expression& operator=(const cpp_expression&) = delete;
|
||||
return *type_;
|
||||
}
|
||||
|
||||
virtual ~cpp_expression() noexcept = default;
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_expression_kind]().
|
||||
cpp_expression_kind kind() const noexcept
|
||||
{
|
||||
return do_get_kind();
|
||||
}
|
||||
|
||||
/// \returns The type of the expression.
|
||||
const cpp_type& type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Creates it given the type.
|
||||
/// \requires The type must not be `nullptr`.
|
||||
cpp_expression(std::unique_ptr<cpp_type> type) : type_(std::move(type)), user_data_(nullptr)
|
||||
{
|
||||
DEBUG_ASSERT(type_ != nullptr, detail::precondition_error_handler{});
|
||||
}
|
||||
|
||||
private:
|
||||
/// \returns The [cppast::cpp_expression_kind]().
|
||||
virtual cpp_expression_kind do_get_kind() const noexcept = 0;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
mutable std::atomic<void*> user_data_;
|
||||
};
|
||||
|
||||
/// An unexposed [cppast::cpp_expression]().
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// There is no further information than a string available.
|
||||
class cpp_unexposed_expression final : public cpp_expression
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to
|
||||
/// maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created unexposed expression.
|
||||
static std::unique_ptr<cpp_unexposed_expression> build(std::unique_ptr<cpp_type> type,
|
||||
cpp_token_string str)
|
||||
{
|
||||
return std::unique_ptr<cpp_unexposed_expression>(
|
||||
new cpp_unexposed_expression(std::move(type), std::move(str)));
|
||||
}
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
/// \returns The expression as a string.
|
||||
const cpp_token_string& expression() const noexcept
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_unexposed_expression(std::unique_ptr<cpp_type> type, cpp_token_string str)
|
||||
: cpp_expression(std::move(type)), str_(std::move(str))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_expression_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_expression_kind::unexposed_t;
|
||||
}
|
||||
|
||||
cpp_token_string str_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_expression]() that is a literal.
|
||||
class cpp_literal_expression final : public cpp_expression
|
||||
protected:
|
||||
/// \effects Creates it given the type.
|
||||
/// \requires The type must not be `nullptr`.
|
||||
cpp_expression(std::unique_ptr<cpp_type> type) : type_(std::move(type)), user_data_(nullptr)
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created literal expression.
|
||||
static std::unique_ptr<cpp_literal_expression> build(std::unique_ptr<cpp_type> type,
|
||||
std::string value)
|
||||
{
|
||||
return std::unique_ptr<cpp_literal_expression>(
|
||||
new cpp_literal_expression(std::move(type), std::move(value)));
|
||||
}
|
||||
DEBUG_ASSERT(type_ != nullptr, detail::precondition_error_handler{});
|
||||
}
|
||||
|
||||
/// \returns The value of the literal, as string.
|
||||
const std::string& value() const noexcept
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
private:
|
||||
/// \returns The [cppast::cpp_expression_kind]().
|
||||
virtual cpp_expression_kind do_get_kind() const noexcept = 0;
|
||||
|
||||
private:
|
||||
cpp_literal_expression(std::unique_ptr<cpp_type> type, std::string value)
|
||||
: cpp_expression(std::move(type)), value_(std::move(value))
|
||||
{
|
||||
}
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
mutable std::atomic<void*> user_data_;
|
||||
};
|
||||
|
||||
cpp_expression_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_expression_kind::literal_t;
|
||||
}
|
||||
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// An unexposed [cppast::cpp_expression]().
|
||||
///
|
||||
/// There is no further information than a string available.
|
||||
class cpp_unexposed_expression final : public cpp_expression
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created unexposed expression.
|
||||
static std::unique_ptr<cpp_unexposed_expression> build(std::unique_ptr<cpp_type> type,
|
||||
cpp_token_string str)
|
||||
{
|
||||
void write_expression(code_generator::output& output, const cpp_expression& expr);
|
||||
} // namespace detail
|
||||
return std::unique_ptr<cpp_unexposed_expression>(
|
||||
new cpp_unexposed_expression(std::move(type), std::move(str)));
|
||||
}
|
||||
|
||||
/// \returns The expression as a string.
|
||||
const cpp_token_string& expression() const noexcept
|
||||
{
|
||||
return str_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_unexposed_expression(std::unique_ptr<cpp_type> type, cpp_token_string str)
|
||||
: cpp_expression(std::move(type)), str_(std::move(str))
|
||||
{}
|
||||
|
||||
cpp_expression_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_expression_kind::unexposed_t;
|
||||
}
|
||||
|
||||
cpp_token_string str_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_expression]() that is a literal.
|
||||
class cpp_literal_expression final : public cpp_expression
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created literal expression.
|
||||
static std::unique_ptr<cpp_literal_expression> build(std::unique_ptr<cpp_type> type,
|
||||
std::string value)
|
||||
{
|
||||
return std::unique_ptr<cpp_literal_expression>(
|
||||
new cpp_literal_expression(std::move(type), std::move(value)));
|
||||
}
|
||||
|
||||
/// \returns The value of the literal, as string.
|
||||
const std::string& value() const noexcept
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_literal_expression(std::unique_ptr<cpp_type> type, std::string value)
|
||||
: cpp_expression(std::move(type)), value_(std::move(value))
|
||||
{}
|
||||
|
||||
cpp_expression_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_expression_kind::literal_t;
|
||||
}
|
||||
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
void write_expression(code_generator::output& output, const cpp_expression& expr);
|
||||
} // namespace detail
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_EXPRESSION_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -7,96 +7,93 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/cpp_entity_container.hpp>
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/cpp_entity_ref.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// An unmatched documentation comment.
|
||||
struct cpp_doc_comment
|
||||
{
|
||||
std::string content;
|
||||
unsigned line;
|
||||
/// An unmatched documentation comment.
|
||||
struct cpp_doc_comment
|
||||
{
|
||||
std::string content;
|
||||
unsigned line;
|
||||
|
||||
cpp_doc_comment(std::string content, unsigned line)
|
||||
: content(std::move(content)), line(line)
|
||||
{
|
||||
}
|
||||
};
|
||||
cpp_doc_comment(std::string content, unsigned line) : content(std::move(content)), line(line) {}
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a file.
|
||||
///
|
||||
/// This is the top-level entity of the AST.
|
||||
class cpp_file final : public cpp_entity, public cpp_entity_container<cpp_file, cpp_entity>
|
||||
/// A [cppast::cpp_entity]() modelling a file.
|
||||
///
|
||||
/// This is the top-level entity of the AST.
|
||||
class cpp_file final : public cpp_entity, public cpp_entity_container<cpp_file, cpp_entity>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_file]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Sets the file name.
|
||||
explicit builder(std::string name) : file_(new cpp_file(std::move(name))) {}
|
||||
|
||||
/// Builds a [cppast::cpp_file]().
|
||||
class builder
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the file name.
|
||||
explicit builder(std::string name) : file_(new cpp_file(std::move(name))) {}
|
||||
file_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
file_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \effects Adds an unmatched documentation comment.
|
||||
void add_unmatched_comment(cpp_doc_comment comment)
|
||||
{
|
||||
file_->comments_.push_back(std::move(comment));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished file.
|
||||
cpp_file& get() noexcept
|
||||
{
|
||||
return *file_;
|
||||
}
|
||||
|
||||
/// \effects Registers the file in the [cppast::cpp_entity_index]().
|
||||
/// It will use the file name as identifier.
|
||||
/// \returns The finished file, or `nullptr`, if that file was already registered.
|
||||
std::unique_ptr<cpp_file> finish(const cpp_entity_index& idx) noexcept
|
||||
{
|
||||
auto res = idx.register_file(cpp_entity_id(file_->name()), type_safe::ref(*file_));
|
||||
return res ? std::move(file_) : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_file> file_;
|
||||
};
|
||||
|
||||
/// \returns The unmatched documentation comments.
|
||||
type_safe::array_ref<const cpp_doc_comment> unmatched_comments() const noexcept
|
||||
/// \effects Adds an unmatched documentation comment.
|
||||
void add_unmatched_comment(cpp_doc_comment comment)
|
||||
{
|
||||
return type_safe::ref(comments_.data(), comments_.size());
|
||||
file_->comments_.push_back(std::move(comment));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished file.
|
||||
cpp_file& get() noexcept
|
||||
{
|
||||
return *file_;
|
||||
}
|
||||
|
||||
/// \effects Registers the file in the [cppast::cpp_entity_index]().
|
||||
/// It will use the file name as identifier.
|
||||
/// \returns The finished file, or `nullptr`, if that file was already registered.
|
||||
std::unique_ptr<cpp_file> finish(const cpp_entity_index& idx) noexcept
|
||||
{
|
||||
auto res = idx.register_file(cpp_entity_id(file_->name()), type_safe::ref(*file_));
|
||||
return res ? std::move(file_) : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_file(std::string name) : cpp_entity(std::move(name)) {}
|
||||
|
||||
/// \returns [cpp_entity_type::file_t]().
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::vector<cpp_doc_comment> comments_;
|
||||
std::unique_ptr<cpp_file> file_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// \returns The unmatched documentation comments.
|
||||
type_safe::array_ref<const cpp_doc_comment> unmatched_comments() const noexcept
|
||||
{
|
||||
struct cpp_file_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
return type_safe::ref(comments_.data(), comments_.size());
|
||||
}
|
||||
|
||||
/// A reference to a [cppast::cpp_file]().
|
||||
using cpp_file_ref = basic_cpp_entity_ref<cpp_file, detail::cpp_file_ref_predicate>;
|
||||
private:
|
||||
cpp_file(std::string name) : cpp_entity(std::move(name)) {}
|
||||
|
||||
/// \returns [cpp_entity_type::file_t]().
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::vector<cpp_doc_comment> comments_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_file_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// A reference to a [cppast::cpp_file]().
|
||||
using cpp_file_ref = basic_cpp_entity_ref<cpp_file, detail::cpp_file_ref_predicate>;
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FILE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -14,104 +14,103 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Mixin base class for all entities that can have a forward declaration.
|
||||
///
|
||||
/// Examples are [cppast::cpp_enum]() or [cppast::cpp_class](),
|
||||
/// but also [cppast::cpp_function_base]().
|
||||
/// Those entities can have multiple declarations and one definition.
|
||||
class cpp_forward_declarable
|
||||
/// Mixin base class for all entities that can have a forward declaration.
|
||||
///
|
||||
/// Examples are [cppast::cpp_enum]() or [cppast::cpp_class](),
|
||||
/// but also [cppast::cpp_function_base]().
|
||||
/// Those entities can have multiple declarations and one definition.
|
||||
class cpp_forward_declarable
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the entity is the definition.
|
||||
bool is_definition() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the entity is the definition.
|
||||
bool is_definition() const noexcept
|
||||
{
|
||||
return !definition_.has_value();
|
||||
}
|
||||
return !definition_.has_value();
|
||||
}
|
||||
|
||||
/// \returns Whether or not the entity is "just" a declaration.
|
||||
bool is_declaration() const noexcept
|
||||
{
|
||||
return definition_.has_value();
|
||||
}
|
||||
/// \returns Whether or not the entity is "just" a declaration.
|
||||
bool is_declaration() const noexcept
|
||||
{
|
||||
return definition_.has_value();
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_entity_id]() of the definition,
|
||||
/// if the current entity is not the definition.
|
||||
const type_safe::optional<cpp_entity_id>& definition() const noexcept
|
||||
{
|
||||
return definition_;
|
||||
}
|
||||
/// \returns The [cppast::cpp_entity_id]() of the definition,
|
||||
/// if the current entity is not the definition.
|
||||
const type_safe::optional<cpp_entity_id>& definition() const noexcept
|
||||
{
|
||||
return definition_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the semantic parent of the entity.
|
||||
/// This applies only to out-of-line definitions
|
||||
/// and is the entity which owns the declaration.
|
||||
const type_safe::optional<cpp_entity_ref>& semantic_parent() const noexcept
|
||||
{
|
||||
return semantic_parent_;
|
||||
}
|
||||
/// \returns A reference to the semantic parent of the entity.
|
||||
/// This applies only to out-of-line definitions
|
||||
/// and is the entity which owns the declaration.
|
||||
const type_safe::optional<cpp_entity_ref>& semantic_parent() const noexcept
|
||||
{
|
||||
return semantic_parent_;
|
||||
}
|
||||
|
||||
/// \returns The name of the semantic parent, if it has one,
|
||||
/// else the empty string.
|
||||
/// \notes This may include template parameters.
|
||||
std::string semantic_scope() const noexcept
|
||||
{
|
||||
return type_safe::copy(semantic_parent_.map(&cpp_entity_ref::name)).value_or("");
|
||||
}
|
||||
/// \returns The name of the semantic parent, if it has one,
|
||||
/// else the empty string.
|
||||
/// \notes This may include template parameters.
|
||||
std::string semantic_scope() const noexcept
|
||||
{
|
||||
return type_safe::copy(semantic_parent_.map(&cpp_entity_ref::name)).value_or("");
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Marks the entity as definition.
|
||||
/// \notes If it is not a definition,
|
||||
/// [*set_definition]() must be called.
|
||||
cpp_forward_declarable() noexcept = default;
|
||||
protected:
|
||||
/// \effects Marks the entity as definition.
|
||||
/// \notes If it is not a definition,
|
||||
/// [*set_definition]() must be called.
|
||||
cpp_forward_declarable() noexcept = default;
|
||||
|
||||
~cpp_forward_declarable() noexcept = default;
|
||||
~cpp_forward_declarable() noexcept = default;
|
||||
|
||||
/// \effects Sets the definition entity,
|
||||
/// marking it as a forward declaration.
|
||||
void mark_declaration(cpp_entity_id def) noexcept
|
||||
{
|
||||
definition_ = std::move(def);
|
||||
}
|
||||
/// \effects Sets the definition entity,
|
||||
/// marking it as a forward declaration.
|
||||
void mark_declaration(cpp_entity_id def) noexcept
|
||||
{
|
||||
definition_ = std::move(def);
|
||||
}
|
||||
|
||||
/// \effects Sets the semantic parent of the entity.
|
||||
void set_semantic_parent(type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||
{
|
||||
semantic_parent_ = std::move(semantic_parent);
|
||||
}
|
||||
/// \effects Sets the semantic parent of the entity.
|
||||
void set_semantic_parent(type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||
{
|
||||
semantic_parent_ = std::move(semantic_parent);
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent_;
|
||||
type_safe::optional<cpp_entity_id> definition_;
|
||||
};
|
||||
private:
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent_;
|
||||
type_safe::optional<cpp_entity_id> definition_;
|
||||
};
|
||||
|
||||
/// \returns Whether or not the given entity is a definition.
|
||||
bool is_definition(const cpp_entity& e) noexcept;
|
||||
/// \returns Whether or not the given entity is a definition.
|
||||
bool is_definition(const cpp_entity& e) noexcept;
|
||||
|
||||
class cpp_enum;
|
||||
class cpp_class;
|
||||
class cpp_variable;
|
||||
class cpp_function_base;
|
||||
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]() (only valid for the generic entity overload),
|
||||
/// returns a reference to the entity itself.
|
||||
/// Otherwise lookups the definition id and returns it.
|
||||
/// \notes The return value will only be `nullptr`, if the definition is not registered.
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_entity> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_entity& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_enum> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_enum& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_class> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_class& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_variable> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_variable& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_function_base> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_function_base& e);
|
||||
/// 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]() (only valid
|
||||
/// for the generic entity overload), returns a reference to the entity itself. Otherwise lookups
|
||||
/// the definition id and returns it. \notes The return value will only be `nullptr`, if the
|
||||
/// definition is not registered. \group get_definition
|
||||
type_safe::optional_ref<const cpp_entity> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_entity& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_enum> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_enum& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_class> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_class& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_variable> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_variable& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_function_base> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_function_base& e);
|
||||
|
||||
} // namespace cppast
|
||||
|
||||
|
|
|
|||
|
|
@ -13,58 +13,58 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() representing a friend declaration.
|
||||
///
|
||||
/// It can either declare or define a `friend` function (template), declare a `friend` class,
|
||||
/// or refer to an existing type.
|
||||
class cpp_friend : public cpp_entity, private cpp_entity_container<cpp_friend, cpp_entity>
|
||||
/// A [cppast::cpp_entity]() representing a friend declaration.
|
||||
///
|
||||
/// It can either declare or define a `friend` function (template), declare a `friend` class,
|
||||
/// or refer to an existing type.
|
||||
class cpp_friend : public cpp_entity, private cpp_entity_container<cpp_friend, cpp_entity>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created friend declaring the given entity as `friend`.
|
||||
/// \notes The friend declaration itself will not be registered,
|
||||
/// but the referring entity is.
|
||||
static std::unique_ptr<cpp_friend> build(std::unique_ptr<cpp_entity> e)
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return std::unique_ptr<cpp_friend>(new cpp_friend(std::move(e)));
|
||||
}
|
||||
|
||||
/// \returns A newly created friend declaring the given entity as `friend`.
|
||||
/// \notes The friend declaration itself will not be registered,
|
||||
/// but the referring entity is.
|
||||
static std::unique_ptr<cpp_friend> build(std::unique_ptr<cpp_entity> e)
|
||||
{
|
||||
return std::unique_ptr<cpp_friend>(new cpp_friend(std::move(e)));
|
||||
}
|
||||
/// \returns A newly created friend declaring the given type as `friend`.
|
||||
/// \notes It will not be registered.
|
||||
static std::unique_ptr<cpp_friend> build(std::unique_ptr<cpp_type> type)
|
||||
{
|
||||
return std::unique_ptr<cpp_friend>(new cpp_friend(std::move(type)));
|
||||
}
|
||||
|
||||
/// \returns A newly created friend declaring the given type as `friend`.
|
||||
/// \notes It will not be registered.
|
||||
static std::unique_ptr<cpp_friend> build(std::unique_ptr<cpp_type> type)
|
||||
{
|
||||
return std::unique_ptr<cpp_friend>(new cpp_friend(std::move(type)));
|
||||
}
|
||||
/// \returns An optional reference to the entity it declares as friend, or `nullptr`.
|
||||
type_safe::optional_ref<const cpp_entity> entity() const noexcept
|
||||
{
|
||||
if (begin() == end())
|
||||
return nullptr;
|
||||
return type_safe::ref(*begin());
|
||||
}
|
||||
|
||||
/// \returns An optional reference to the entity it declares as friend, or `nullptr`.
|
||||
type_safe::optional_ref<const cpp_entity> entity() const noexcept
|
||||
{
|
||||
if (begin() == end())
|
||||
return nullptr;
|
||||
return type_safe::ref(*begin());
|
||||
}
|
||||
/// \returns An optional reference to the type it declares as friend, or `nullptr`.
|
||||
type_safe::optional_ref<const cpp_type> type() const noexcept
|
||||
{
|
||||
return type_safe::opt_ref(type_.get());
|
||||
}
|
||||
|
||||
/// \returns An optional reference to the type it declares as friend, or `nullptr`.
|
||||
type_safe::optional_ref<const cpp_type> type() const noexcept
|
||||
{
|
||||
return type_safe::opt_ref(type_.get());
|
||||
}
|
||||
private:
|
||||
cpp_friend(std::unique_ptr<cpp_entity> e) : cpp_entity("")
|
||||
{
|
||||
add_child(std::move(e));
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_friend(std::unique_ptr<cpp_entity> e) : cpp_entity("")
|
||||
{
|
||||
add_child(std::move(e));
|
||||
}
|
||||
cpp_friend(std::unique_ptr<cpp_type> type) : cpp_entity(""), type_(std::move(type)) {}
|
||||
|
||||
cpp_friend(std::unique_ptr<cpp_type> type) : cpp_entity(""), type_(std::move(type)) {}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
|
||||
friend cpp_entity_container<cpp_friend, cpp_entity>;
|
||||
};
|
||||
friend cpp_entity_container<cpp_friend, cpp_entity>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FRIEND_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -5,262 +5,261 @@
|
|||
#ifndef CPPAST_CPP_FUNCTION_HPP_INCLUDED
|
||||
#define CPPAST_CPP_FUNCTION_HPP_INCLUDED
|
||||
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_forward_declarable.hpp>
|
||||
#include <cppast/cpp_storage_class_specifiers.hpp>
|
||||
#include <cppast/cpp_variable_base.hpp>
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a function parameter.
|
||||
class cpp_function_parameter final : public cpp_entity, public cpp_variable_base
|
||||
/// A [cppast::cpp_entity]() modelling a function parameter.
|
||||
class cpp_function_parameter final : public cpp_entity, public cpp_variable_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered function parameter.
|
||||
static std::unique_ptr<cpp_function_parameter> build(const cpp_entity_index& idx,
|
||||
cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def
|
||||
= nullptr);
|
||||
|
||||
/// \returns A newly created unnamed function parameter.
|
||||
/// \notes It will not be registered, as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_function_parameter> build(std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def
|
||||
= nullptr);
|
||||
|
||||
private:
|
||||
cpp_function_parameter(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def)
|
||||
: cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// The kinds of function bodies of a [cppast::cpp_function_base]().
|
||||
enum cpp_function_body_kind
|
||||
{
|
||||
cpp_function_declaration, //< Just a declaration.
|
||||
cpp_function_definition, //< Regular definition.
|
||||
cpp_function_defaulted, //< Defaulted definition.
|
||||
cpp_function_deleted, //< Deleted definition.
|
||||
};
|
||||
|
||||
/// \returns Whether or not the function body is a declaration,
|
||||
/// without a definition.
|
||||
inline bool is_declaration(cpp_function_body_kind body) noexcept
|
||||
{
|
||||
return body == cpp_function_declaration;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the function body is a definition.
|
||||
inline bool is_definition(cpp_function_body_kind body) noexcept
|
||||
{
|
||||
return !is_declaration(body);
|
||||
}
|
||||
|
||||
/// Base class for all entities that are functions.
|
||||
///
|
||||
/// It contains arguments and common flags.
|
||||
class cpp_function_base : public cpp_entity, public cpp_forward_declarable
|
||||
{
|
||||
public:
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_function__parameter]()
|
||||
/// entities.
|
||||
detail::iteratable_intrusive_list<cpp_function_parameter> parameters() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered function parameter.
|
||||
static std::unique_ptr<cpp_function_parameter> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def = nullptr);
|
||||
|
||||
/// \returns A newly created unnamed function parameter.
|
||||
/// \notes It will not be registered, as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_function_parameter> build(
|
||||
std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def = nullptr);
|
||||
|
||||
private:
|
||||
cpp_function_parameter(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def)
|
||||
: cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// The kinds of function bodies of a [cppast::cpp_function_base]().
|
||||
enum cpp_function_body_kind
|
||||
{
|
||||
cpp_function_declaration, //< Just a declaration.
|
||||
cpp_function_definition, //< Regular definition.
|
||||
cpp_function_defaulted, //< Defaulted definition.
|
||||
cpp_function_deleted, //< Deleted definition.
|
||||
};
|
||||
|
||||
/// \returns Whether or not the function body is a declaration,
|
||||
/// without a definition.
|
||||
inline bool is_declaration(cpp_function_body_kind body) noexcept
|
||||
{
|
||||
return body == cpp_function_declaration;
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns Whether or not the function body is a definition.
|
||||
inline bool is_definition(cpp_function_body_kind body) noexcept
|
||||
/// \returns The [cppast::cpp_function_body_kind]().
|
||||
/// \notes This matches the [cppast::cpp_forward_declarable]() queries.
|
||||
cpp_function_body_kind body_kind() const noexcept
|
||||
{
|
||||
return !is_declaration(body);
|
||||
return body_;
|
||||
}
|
||||
|
||||
/// Base class for all entities that are functions.
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the given
|
||||
/// `noexcept` condition. \notes If this returns `nullptr`, the function has the implicit
|
||||
/// noexcept value (i.e. none, unless it is a destructor). \notes There is no way to distinguish
|
||||
/// between `noexcept` and `noexcept(true)`.
|
||||
type_safe::optional_ref<const cpp_expression> noexcept_condition() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(noexcept_expr_.get());
|
||||
}
|
||||
|
||||
/// \returns Whether the function has an ellipsis.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
|
||||
/// \returns The signature of the function,
|
||||
/// i.e. parameters and cv/ref-qualifiers if a member function.
|
||||
/// It has the form `(int,char,...) const`.
|
||||
std::string signature() const
|
||||
{
|
||||
return do_get_signature();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for functions.
|
||||
///
|
||||
/// It contains arguments and common flags.
|
||||
class cpp_function_base : public cpp_entity, public cpp_forward_declarable
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <typename T>
|
||||
class basic_builder
|
||||
{
|
||||
public:
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_function__parameter]() entities.
|
||||
detail::iteratable_intrusive_list<cpp_function_parameter> parameters() const noexcept
|
||||
/// \effects Sets the name.
|
||||
basic_builder(std::string name) : function(new T(name)) {}
|
||||
|
||||
/// \effects Adds a parameter.
|
||||
void add_parameter(std::unique_ptr<cpp_function_parameter> parameter)
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
static_cast<cpp_function_base&>(*function).parameters_.push_back(*function,
|
||||
std::move(parameter));
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_function_body_kind]().
|
||||
/// \notes This matches the [cppast::cpp_forward_declarable]() queries.
|
||||
cpp_function_body_kind body_kind() const noexcept
|
||||
/// \effects Marks the function as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
return body_;
|
||||
static_cast<cpp_function_base&>(*function).variadic_ = true;
|
||||
}
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the given `noexcept` condition.
|
||||
/// \notes If this returns `nullptr`, the function has the implicit noexcept value (i.e. none, unless it is a destructor).
|
||||
/// \notes There is no way to distinguish between `noexcept` and `noexcept(true)`.
|
||||
type_safe::optional_ref<const cpp_expression> noexcept_condition() const noexcept
|
||||
/// \effects Sets the noexcept condition expression.
|
||||
void noexcept_condition(std::unique_ptr<cpp_expression> cond)
|
||||
{
|
||||
return type_safe::opt_cref(noexcept_expr_.get());
|
||||
static_cast<cpp_function_base&>(*function).noexcept_expr_ = std::move(cond);
|
||||
}
|
||||
|
||||
/// \returns Whether the function has an ellipsis.
|
||||
bool is_variadic() const noexcept
|
||||
/// \returns The not yet finished function.
|
||||
T& get() noexcept
|
||||
{
|
||||
return variadic_;
|
||||
return *function;
|
||||
}
|
||||
|
||||
/// \returns The signature of the function,
|
||||
/// i.e. parameters and cv/ref-qualifiers if a member function.
|
||||
/// It has the form `(int,char,...) const`.
|
||||
std::string signature() const
|
||||
/// \effects If the body is a definition, registers it.
|
||||
/// Else marks it as a declaration.
|
||||
/// \returns The finished function.
|
||||
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
cpp_function_body_kind body_kind,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||
{
|
||||
return do_get_signature();
|
||||
function->body_ = body_kind;
|
||||
function->set_semantic_parent(std::move(semantic_parent));
|
||||
if (cppast::is_definition(body_kind))
|
||||
idx.register_definition(std::move(id), type_safe::ref(*function));
|
||||
else
|
||||
{
|
||||
function->mark_declaration(id);
|
||||
idx.register_forward_declaration(std::move(id), type_safe::ref(*function));
|
||||
}
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
/// \returns The finished function without registering it.
|
||||
/// \notes This is intended for templated functions only.
|
||||
std::unique_ptr<T> finish(cpp_entity_id id, cpp_function_body_kind body_kind,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||
{
|
||||
function->body_ = body_kind;
|
||||
function->set_semantic_parent(std::move(semantic_parent));
|
||||
if (!cppast::is_definition(body_kind))
|
||||
function->mark_declaration(id);
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for functions.
|
||||
///
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <typename T>
|
||||
class basic_builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name.
|
||||
basic_builder(std::string name) : function(new T(name)) {}
|
||||
basic_builder() = default;
|
||||
~basic_builder() noexcept = default;
|
||||
|
||||
/// \effects Adds a parameter.
|
||||
void add_parameter(std::unique_ptr<cpp_function_parameter> parameter)
|
||||
{
|
||||
static_cast<cpp_function_base&>(*function).parameters_.push_back(*function,
|
||||
std::move(
|
||||
parameter));
|
||||
}
|
||||
|
||||
/// \effects Marks the function as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
static_cast<cpp_function_base&>(*function).variadic_ = true;
|
||||
}
|
||||
|
||||
/// \effects Sets the noexcept condition expression.
|
||||
void noexcept_condition(std::unique_ptr<cpp_expression> cond)
|
||||
{
|
||||
static_cast<cpp_function_base&>(*function).noexcept_expr_ = std::move(cond);
|
||||
}
|
||||
|
||||
/// \returns The not yet finished function.
|
||||
T& get() noexcept
|
||||
{
|
||||
return *function;
|
||||
}
|
||||
|
||||
/// \effects If the body is a definition, registers it.
|
||||
/// Else marks it as a declaration.
|
||||
/// \returns The finished function.
|
||||
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
cpp_function_body_kind body_kind,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||
{
|
||||
function->body_ = body_kind;
|
||||
function->set_semantic_parent(std::move(semantic_parent));
|
||||
if (cppast::is_definition(body_kind))
|
||||
idx.register_definition(std::move(id), type_safe::ref(*function));
|
||||
else
|
||||
{
|
||||
function->mark_declaration(id);
|
||||
idx.register_forward_declaration(std::move(id), type_safe::ref(*function));
|
||||
}
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
/// \returns The finished function without registering it.
|
||||
/// \notes This is intended for templated functions only.
|
||||
std::unique_ptr<T> finish(cpp_entity_id id, cpp_function_body_kind body_kind,
|
||||
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||
{
|
||||
function->body_ = body_kind;
|
||||
function->set_semantic_parent(std::move(semantic_parent));
|
||||
if (!cppast::is_definition(body_kind))
|
||||
function->mark_declaration(id);
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
protected:
|
||||
basic_builder() = default;
|
||||
~basic_builder() noexcept = default;
|
||||
|
||||
std::unique_ptr<T> function;
|
||||
};
|
||||
|
||||
cpp_function_base(std::string name)
|
||||
: cpp_entity(std::move(name)), body_(cpp_function_declaration), variadic_(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \returns The signature, it is called by [*signature()]().
|
||||
virtual std::string do_get_signature() const;
|
||||
|
||||
private:
|
||||
detail::intrusive_list<cpp_function_parameter> parameters_;
|
||||
std::unique_ptr<cpp_expression> noexcept_expr_;
|
||||
cpp_function_body_kind body_;
|
||||
bool variadic_;
|
||||
std::unique_ptr<T> function;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ function.
|
||||
/// \notes This is not a member function,
|
||||
/// use [cppast::cpp_member_function]() for that.
|
||||
/// It can be a `static` function of a class, however.
|
||||
class cpp_function final : public cpp_function_base
|
||||
cpp_function_base(std::string name)
|
||||
: cpp_entity(std::move(name)), body_(cpp_function_declaration), variadic_(false)
|
||||
{}
|
||||
|
||||
protected:
|
||||
/// \returns The signature, it is called by [*signature()]().
|
||||
virtual std::string do_get_signature() const;
|
||||
|
||||
private:
|
||||
detail::intrusive_list<cpp_function_parameter> parameters_;
|
||||
std::unique_ptr<cpp_expression> noexcept_expr_;
|
||||
cpp_function_body_kind body_;
|
||||
bool variadic_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ function.
|
||||
/// \notes This is not a member function,
|
||||
/// use [cppast::cpp_member_function]() for that.
|
||||
/// It can be a `static` function of a class, however.
|
||||
class cpp_function final : public cpp_function_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_function]().
|
||||
class builder : public cpp_function_base::basic_builder<cpp_function>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_function]().
|
||||
class builder : public cpp_function_base::basic_builder<cpp_function>
|
||||
/// \effects Sets the name and return type.
|
||||
builder(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name and return type.
|
||||
builder(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
{
|
||||
function = std::unique_ptr<cpp_function>(
|
||||
new cpp_function(std::move(name), std::move(return_type)));
|
||||
}
|
||||
|
||||
/// \effects Sets the storage class.
|
||||
void storage_class(cpp_storage_class_specifiers storage)
|
||||
{
|
||||
function->storage_ = storage;
|
||||
}
|
||||
|
||||
/// \effects Marks the function as `constexpr`.
|
||||
void is_constexpr()
|
||||
{
|
||||
function->constexpr_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
return *return_type_;
|
||||
function = std::unique_ptr<cpp_function>(
|
||||
new cpp_function(std::move(name), std::move(return_type)));
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_storage_specifiers]() of the function.
|
||||
/// \notes If it is `cpp_storage_class_static` and inside a [cppast::cpp_class](),
|
||||
/// it is a `static` class function.
|
||||
cpp_storage_class_specifiers storage_class() const noexcept
|
||||
/// \effects Sets the storage class.
|
||||
void storage_class(cpp_storage_class_specifiers storage)
|
||||
{
|
||||
return storage_;
|
||||
function->storage_ = storage;
|
||||
}
|
||||
|
||||
/// \returns Whether the function is marked `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
/// \effects Marks the function as `constexpr`.
|
||||
void is_constexpr()
|
||||
{
|
||||
return constexpr_;
|
||||
function->constexpr_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_function(std::string name, std::unique_ptr<cpp_type> ret)
|
||||
: cpp_function_base(std::move(name)),
|
||||
return_type_(std::move(ret)),
|
||||
storage_(cpp_storage_class_auto),
|
||||
constexpr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
cpp_storage_class_specifiers storage_;
|
||||
bool constexpr_;
|
||||
};
|
||||
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
return *return_type_;
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_storage_specifiers]() of the function.
|
||||
/// \notes If it is `cpp_storage_class_static` and inside a [cppast::cpp_class](),
|
||||
/// it is a `static` class function.
|
||||
cpp_storage_class_specifiers storage_class() const noexcept
|
||||
{
|
||||
return storage_;
|
||||
}
|
||||
|
||||
/// \returns Whether the function is marked `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return constexpr_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_function(std::string name, std::unique_ptr<cpp_type> ret)
|
||||
: cpp_function_base(std::move(name)), return_type_(std::move(ret)),
|
||||
storage_(cpp_storage_class_auto), constexpr_(false)
|
||||
{}
|
||||
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
cpp_storage_class_specifiers storage_;
|
||||
bool constexpr_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FUNCTION_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,70 +10,68 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a function template.
|
||||
class cpp_function_template final : public cpp_template
|
||||
/// A [cppast::cpp_entity]() modelling a function template.
|
||||
class cpp_function_template final : public cpp_template
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_function_template]().
|
||||
class builder : public basic_builder<cpp_function_template, cpp_function_base>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_function_template]().
|
||||
class builder : public basic_builder<cpp_function_template, cpp_function_base>
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// A reference to the function that is being templated.
|
||||
const cpp_function_base& function() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_function_base&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_function_template(std::unique_ptr<cpp_function_base> func)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(func.release()))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_function_template, cpp_function_base>;
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a function template specialization.
|
||||
class cpp_function_template_specialization final : public cpp_template_specialization
|
||||
/// A reference to the function that is being templated.
|
||||
const cpp_function_base& function() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_function_base&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_function_template(std::unique_ptr<cpp_function_base> func)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(func.release()))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_function_template, cpp_function_base>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a function template specialization.
|
||||
class cpp_function_template_specialization final : public cpp_template_specialization
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_function_template_specialization]().
|
||||
class builder
|
||||
: public specialization_builder<cpp_function_template_specialization, cpp_function_base>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_function_template_specialization]().
|
||||
class builder
|
||||
: public specialization_builder<cpp_function_template_specialization, cpp_function_base>
|
||||
{
|
||||
public:
|
||||
using specialization_builder::specialization_builder;
|
||||
|
||||
private:
|
||||
using specialization_builder::add_parameter;
|
||||
};
|
||||
|
||||
/// A reference to the function that is being specialized.
|
||||
const cpp_function_base& function() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_function_base&>(*begin());
|
||||
}
|
||||
using specialization_builder::specialization_builder;
|
||||
|
||||
private:
|
||||
cpp_function_template_specialization(std::unique_ptr<cpp_function_base> func,
|
||||
cpp_template_ref primary)
|
||||
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend specialization_builder<cpp_function_template_specialization, cpp_function_base>;
|
||||
using specialization_builder::add_parameter;
|
||||
};
|
||||
|
||||
/// A reference to the function that is being specialized.
|
||||
const cpp_function_base& function() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_function_base&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_function_template_specialization(std::unique_ptr<cpp_function_base> func,
|
||||
cpp_template_ref primary)
|
||||
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend specialization_builder<cpp_function_template_specialization, cpp_function_base>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -9,199 +9,195 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_type]() that is a function.
|
||||
///
|
||||
/// A function pointer is created by wrapping it in [cppast::cpp_pointer_type]().
|
||||
class cpp_function_type final : public cpp_type
|
||||
/// A [cppast::cpp_type]() that is a function.
|
||||
///
|
||||
/// A function pointer is created by wrapping it in [cppast::cpp_pointer_type]().
|
||||
class cpp_function_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_function_type]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_function_type]().
|
||||
class builder
|
||||
/// \effects Sets the return type.
|
||||
explicit builder(std::unique_ptr<cpp_type> return_type)
|
||||
: func_(new cpp_function_type(std::move(return_type)))
|
||||
{}
|
||||
|
||||
/// \effects Adds an parameter type.
|
||||
void add_parameter(std::unique_ptr<cpp_type> arg)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the return type.
|
||||
explicit builder(std::unique_ptr<cpp_type> return_type)
|
||||
: func_(new cpp_function_type(std::move(return_type)))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Adds an parameter type.
|
||||
void add_parameter(std::unique_ptr<cpp_type> arg)
|
||||
{
|
||||
func_->parameters_.push_back(*func_, std::move(arg));
|
||||
}
|
||||
|
||||
/// \effects Adds an ellipsis, marking it as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
func_->variadic_ = true;
|
||||
}
|
||||
|
||||
/// \returns The finished [cppast::cpp_function_type]().
|
||||
std::unique_ptr<cpp_function_type> finish()
|
||||
{
|
||||
return std::move(func_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_function_type> func_;
|
||||
};
|
||||
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
return *return_type_;
|
||||
func_->parameters_.push_back(*func_, std::move(arg));
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the parameter types.
|
||||
detail::iteratable_intrusive_list<cpp_type> parameter_types() const noexcept
|
||||
/// \effects Adds an ellipsis, marking it as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
func_->variadic_ = true;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the function is variadic (C-style ellipsis).
|
||||
bool is_variadic() const noexcept
|
||||
/// \returns The finished [cppast::cpp_function_type]().
|
||||
std::unique_ptr<cpp_function_type> finish()
|
||||
{
|
||||
return variadic_;
|
||||
return std::move(func_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_function_type(std::unique_ptr<cpp_type> return_type)
|
||||
: return_type_(std::move(return_type)), variadic_(false)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::function_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
detail::intrusive_list<cpp_type> parameters_;
|
||||
bool variadic_;
|
||||
std::unique_ptr<cpp_function_type> func_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that is a member function.
|
||||
///
|
||||
/// A member function with cv qualifier is created by wrapping it in [cppast::cpp_cv_qualified_type]().
|
||||
/// A member function with reference qualifier is created by wrapping it in [cppast::cpp_reference_type]().
|
||||
/// A member function pointer is created by wrapping it in [cppast::cpp_pointer_type]().
|
||||
class cpp_member_function_type final : public cpp_type
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
return *return_type_;
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the parameter types.
|
||||
detail::iteratable_intrusive_list<cpp_type> parameter_types() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns Whether or not the function is variadic (C-style ellipsis).
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_function_type(std::unique_ptr<cpp_type> return_type)
|
||||
: return_type_(std::move(return_type)), variadic_(false)
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::function_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
detail::intrusive_list<cpp_type> parameters_;
|
||||
bool variadic_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that is a member function.
|
||||
///
|
||||
/// A member function with cv qualifier is created by wrapping it in
|
||||
/// [cppast::cpp_cv_qualified_type](). A member function with reference qualifier is created by
|
||||
/// wrapping it in [cppast::cpp_reference_type](). A member function pointer is created by wrapping
|
||||
/// it in [cppast::cpp_pointer_type]().
|
||||
class cpp_member_function_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_member_function_type]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_member_function_type]().
|
||||
class builder
|
||||
/// \effects Sets the class and return type.
|
||||
builder(std::unique_ptr<cpp_type> class_type, std::unique_ptr<cpp_type> return_type)
|
||||
: func_(new cpp_member_function_type(std::move(class_type), std::move(return_type)))
|
||||
{}
|
||||
|
||||
/// \effects Adds a parameter type.
|
||||
void add_parameter(std::unique_ptr<cpp_type> arg)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the class and return type.
|
||||
builder(std::unique_ptr<cpp_type> class_type, std::unique_ptr<cpp_type> return_type)
|
||||
: func_(new cpp_member_function_type(std::move(class_type), std::move(return_type)))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Adds a parameter type.
|
||||
void add_parameter(std::unique_ptr<cpp_type> arg)
|
||||
{
|
||||
func_->parameters_.push_back(*func_, std::move(arg));
|
||||
}
|
||||
|
||||
/// \effects Adds an ellipsis, marking it as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
func_->variadic_ = true;
|
||||
}
|
||||
|
||||
/// \returns The finished [cppast::cpp_member_function_type]().
|
||||
std::unique_ptr<cpp_member_function_type> finish()
|
||||
{
|
||||
return std::move(func_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_member_function_type> func_;
|
||||
};
|
||||
|
||||
/// \returns A reference to the class [cppast::cpp_type]().
|
||||
const cpp_type& class_type() const noexcept
|
||||
{
|
||||
return *class_type_;
|
||||
func_->parameters_.push_back(*func_, std::move(arg));
|
||||
}
|
||||
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
/// \effects Adds an ellipsis, marking it as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
return *return_type_;
|
||||
func_->variadic_ = true;
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the parameter types.
|
||||
detail::iteratable_intrusive_list<cpp_type> parameter_types() const noexcept
|
||||
/// \returns The finished [cppast::cpp_member_function_type]().
|
||||
std::unique_ptr<cpp_member_function_type> finish()
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns Whether or not the function is variadic (C-style ellipsis).
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
return std::move(func_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_member_function_type(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> return_type)
|
||||
: class_type_(std::move(class_type)), return_type_(std::move(return_type)), variadic_(false)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::member_function_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> class_type_, return_type_;
|
||||
detail::intrusive_list<cpp_type> parameters_;
|
||||
bool variadic_;
|
||||
std::unique_ptr<cpp_member_function_type> func_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that is a member object.
|
||||
///
|
||||
/// A member object pointer is created by wrapping it in [cppast::cpp_pointer_type]().
|
||||
class cpp_member_object_type final : public cpp_type
|
||||
/// \returns A reference to the class [cppast::cpp_type]().
|
||||
const cpp_type& class_type() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created member object type.
|
||||
static std::unique_ptr<cpp_member_object_type> build(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> object_type)
|
||||
{
|
||||
return std::unique_ptr<cpp_member_object_type>(
|
||||
new cpp_member_object_type(std::move(class_type), std::move(object_type)));
|
||||
}
|
||||
return *class_type_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the class [cppast::cpp_type]().
|
||||
const cpp_type& class_type() const noexcept
|
||||
{
|
||||
return *class_type_;
|
||||
}
|
||||
/// \returns A reference to the return [cppast::cpp_type]().
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
return *return_type_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the object [cppast::cpp_type]().
|
||||
const cpp_type& object_type() const noexcept
|
||||
{
|
||||
return *object_type_;
|
||||
}
|
||||
/// \returns An iteratable object iterating over the parameter types.
|
||||
detail::iteratable_intrusive_list<cpp_type> parameter_types() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_member_object_type(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> object_type)
|
||||
: class_type_(std::move(class_type)), object_type_(std::move(object_type))
|
||||
{
|
||||
}
|
||||
/// \returns Whether or not the function is variadic (C-style ellipsis).
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::member_object_t;
|
||||
}
|
||||
private:
|
||||
cpp_member_function_type(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> return_type)
|
||||
: class_type_(std::move(class_type)), return_type_(std::move(return_type)), variadic_(false)
|
||||
{}
|
||||
|
||||
std::unique_ptr<cpp_type> class_type_, object_type_;
|
||||
};
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::member_function_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> class_type_, return_type_;
|
||||
detail::intrusive_list<cpp_type> parameters_;
|
||||
bool variadic_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that is a member object.
|
||||
///
|
||||
/// A member object pointer is created by wrapping it in [cppast::cpp_pointer_type]().
|
||||
class cpp_member_object_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created member object type.
|
||||
static std::unique_ptr<cpp_member_object_type> build(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> object_type)
|
||||
{
|
||||
return std::unique_ptr<cpp_member_object_type>(
|
||||
new cpp_member_object_type(std::move(class_type), std::move(object_type)));
|
||||
}
|
||||
|
||||
/// \returns A reference to the class [cppast::cpp_type]().
|
||||
const cpp_type& class_type() const noexcept
|
||||
{
|
||||
return *class_type_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the object [cppast::cpp_type]().
|
||||
const cpp_type& object_type() const noexcept
|
||||
{
|
||||
return *object_type_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_member_object_type(std::unique_ptr<cpp_type> class_type,
|
||||
std::unique_ptr<cpp_type> object_type)
|
||||
: class_type_(std::move(class_type)), object_type_(std::move(object_type))
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::member_object_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> class_type_, object_type_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FUNCTION_TYPE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,53 +10,51 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a language linkage.
|
||||
class cpp_language_linkage final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_language_linkage, cpp_entity>
|
||||
/// A [cppast::cpp_entity]() modelling a language linkage.
|
||||
class cpp_language_linkage final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_language_linkage, cpp_entity>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_language_linkage]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Sets the name, that is the kind of language linkage.
|
||||
explicit builder(std::string name) : linkage_(new cpp_language_linkage(std::move(name))) {}
|
||||
|
||||
/// Builds a [cppast::cpp_language_linkage]().
|
||||
class builder
|
||||
/// \effects Adds an entity to the language linkage.
|
||||
void add_child(std::unique_ptr<cpp_entity> child)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name, that is the kind of language linkage.
|
||||
explicit builder(std::string name) : linkage_(new cpp_language_linkage(std::move(name)))
|
||||
{
|
||||
}
|
||||
linkage_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \effects Adds an entity to the language linkage.
|
||||
void add_child(std::unique_ptr<cpp_entity> child)
|
||||
{
|
||||
linkage_->add_child(std::move(child));
|
||||
}
|
||||
/// \returns The not yet finished language linkage.
|
||||
cpp_language_linkage& get() const noexcept
|
||||
{
|
||||
return *linkage_;
|
||||
}
|
||||
|
||||
/// \returns The not yet finished language linkage.
|
||||
cpp_language_linkage& get() const noexcept
|
||||
{
|
||||
return *linkage_;
|
||||
}
|
||||
|
||||
/// \returns The finalized language linkage.
|
||||
/// \notes It is not registered on purpose as nothing can refer to it.
|
||||
std::unique_ptr<cpp_language_linkage> finish()
|
||||
{
|
||||
return std::move(linkage_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_language_linkage> linkage_;
|
||||
};
|
||||
|
||||
/// \returns `true` if the linkage is a block, `false` otherwise.
|
||||
bool is_block() const noexcept;
|
||||
/// \returns The finalized language linkage.
|
||||
/// \notes It is not registered on purpose as nothing can refer to it.
|
||||
std::unique_ptr<cpp_language_linkage> finish()
|
||||
{
|
||||
return std::move(linkage_);
|
||||
}
|
||||
|
||||
private:
|
||||
using cpp_entity::cpp_entity;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
std::unique_ptr<cpp_language_linkage> linkage_;
|
||||
};
|
||||
|
||||
/// \returns `true` if the linkage is a block, `false` otherwise.
|
||||
bool is_block() const noexcept;
|
||||
|
||||
private:
|
||||
using cpp_entity::cpp_entity;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -11,312 +11,305 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// The `virtual`-ness of a member function.
|
||||
///
|
||||
/// This is a [ts::flag_set]() `enum`.
|
||||
/// \notes It does not specify whether a member function is `virtual` or not,
|
||||
/// only the kind of `virtual`.
|
||||
/// \notes As surprising as it may be, any of these can be used in combination,
|
||||
/// i.e. you can have a `final` non-overriding function or an overriding pure `virtual` function.
|
||||
enum class cpp_virtual_flags
|
||||
/// The `virtual`-ness of a member function.
|
||||
///
|
||||
/// This is a [ts::flag_set]() `enum`.
|
||||
/// \notes It does not specify whether a member function is `virtual` or not,
|
||||
/// only the kind of `virtual`.
|
||||
/// \notes As surprising as it may be, any of these can be used in combination,
|
||||
/// i.e. you can have a `final` non-overriding function or an overriding pure `virtual` function.
|
||||
enum class cpp_virtual_flags
|
||||
{
|
||||
pure, //< Set if the function is pure.
|
||||
override, //< Set if the function overrides a base class function.
|
||||
final, //< Set if the function is marked `final`.
|
||||
|
||||
_flag_set_size, //< \exclude
|
||||
};
|
||||
|
||||
/// The `virtual` information of a member function.
|
||||
///
|
||||
/// This is an optional of the combination of the [cppast::cpp_virtual_flags]().
|
||||
/// If the optional has a value, the member function is `virtual`,
|
||||
/// and the [ts::flag_set]() describes additional information.
|
||||
using cpp_virtual = type_safe::optional<type_safe::flag_set<cpp_virtual_flags>>;
|
||||
|
||||
/// \returns Whether or not a member function is `virtual`.
|
||||
inline bool is_virtual(const cpp_virtual& virt) noexcept
|
||||
{
|
||||
return virt.has_value();
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function is pure.
|
||||
inline bool is_pure(const cpp_virtual& virt) noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::final) & cpp_virtual_flags::pure);
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function overrides another one.
|
||||
inline bool is_overriding(const cpp_virtual& virt) noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::override);
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function is `final`.
|
||||
inline bool is_final(const cpp_virtual& virt) noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::final);
|
||||
}
|
||||
|
||||
/// Base classes for all regular member function.
|
||||
///
|
||||
/// The two derived classes are [cppast::cpp_member_function]() and [cppast::cpp_conversion_op]().
|
||||
class cpp_member_function_base : public cpp_function_base
|
||||
{
|
||||
public:
|
||||
/// \returns The return type of the member function.
|
||||
const cpp_type& return_type() const noexcept
|
||||
{
|
||||
pure, //< Set if the function is pure.
|
||||
override, //< Set if the function overrides a base class function.
|
||||
final, //< Set if the function is marked `final`.
|
||||
|
||||
_flag_set_size, //< \exclude
|
||||
};
|
||||
|
||||
/// The `virtual` information of a member function.
|
||||
///
|
||||
/// This is an optional of the combination of the [cppast::cpp_virtual_flags]().
|
||||
/// If the optional has a value, the member function is `virtual`,
|
||||
/// and the [ts::flag_set]() describes additional information.
|
||||
using cpp_virtual = type_safe::optional<type_safe::flag_set<cpp_virtual_flags>>;
|
||||
|
||||
/// \returns Whether or not a member function is `virtual`.
|
||||
inline bool is_virtual(const cpp_virtual& virt) noexcept
|
||||
{
|
||||
return virt.has_value();
|
||||
return *return_type_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function is pure.
|
||||
inline bool is_pure(const cpp_virtual& virt) noexcept
|
||||
/// \returns Whether or not it is `virtual`.
|
||||
bool is_virtual() const noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::final) & cpp_virtual_flags::pure);
|
||||
return virtual_info().has_value();
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function overrides another one.
|
||||
inline bool is_overriding(const cpp_virtual& virt) noexcept
|
||||
/// \returns The `virtual`-ness of the member function.
|
||||
const cpp_virtual& virtual_info() const noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure)
|
||||
& cpp_virtual_flags::override);
|
||||
return virtual_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not a member function is `final`.
|
||||
inline bool is_final(const cpp_virtual& virt) noexcept
|
||||
/// \returns The cv-qualifier on the member function.
|
||||
cpp_cv cv_qualifier() const noexcept
|
||||
{
|
||||
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::final);
|
||||
return cv_;
|
||||
}
|
||||
|
||||
/// Base classes for all regular member function.
|
||||
///
|
||||
/// The two derived classes are [cppast::cpp_member_function]() and [cppast::cpp_conversion_op]().
|
||||
class cpp_member_function_base : public cpp_function_base
|
||||
/// \returns The ref-qualifier on the member function.
|
||||
cpp_reference ref_qualifier() const noexcept
|
||||
{
|
||||
return ref_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the member function is `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return constexpr_;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for member functions.
|
||||
template <typename T>
|
||||
class basic_member_builder : public basic_builder<T>
|
||||
{
|
||||
public:
|
||||
/// \returns The return type of the member function.
|
||||
const cpp_type& return_type() const noexcept
|
||||
/// \effects Sets the name and return type.
|
||||
basic_member_builder(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
{
|
||||
return *return_type_;
|
||||
this->function = std::unique_ptr<T>(new T(std::move(name), std::move(return_type)));
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is `virtual`.
|
||||
bool is_virtual() const noexcept
|
||||
/// \effects Sets the cv- and ref-qualifier.
|
||||
void cv_ref_qualifier(cpp_cv cv, cpp_reference ref) noexcept
|
||||
{
|
||||
return virtual_info().has_value();
|
||||
auto& base = static_cast<cpp_member_function_base&>(*this->function);
|
||||
base.cv_ = cv;
|
||||
base.ref_ = ref;
|
||||
}
|
||||
|
||||
/// \returns The `virtual`-ness of the member function.
|
||||
const cpp_virtual& virtual_info() const noexcept
|
||||
/// \effects Sets the `virtual`-ness of the function.
|
||||
void virtual_info(type_safe::flag_set<cpp_virtual_flags> virt) noexcept
|
||||
{
|
||||
return virtual_;
|
||||
static_cast<cpp_member_function_base&>(*this->function).virtual_ = virt;
|
||||
}
|
||||
|
||||
/// \returns The cv-qualifier on the member function.
|
||||
cpp_cv cv_qualifier() const noexcept
|
||||
/// \effects Marks the function as `constexpr`.
|
||||
void is_constexpr() noexcept
|
||||
{
|
||||
return cv_;
|
||||
}
|
||||
|
||||
/// \returns The ref-qualifier on the member function.
|
||||
cpp_reference ref_qualifier() const noexcept
|
||||
{
|
||||
return ref_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the member function is `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return constexpr_;
|
||||
static_cast<cpp_member_function_base&>(*this->function).constexpr_ = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for member functions.
|
||||
template <typename T>
|
||||
class basic_member_builder : public basic_builder<T>
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name and return type.
|
||||
basic_member_builder(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
{
|
||||
this->function = std::unique_ptr<T>(new T(std::move(name), std::move(return_type)));
|
||||
}
|
||||
|
||||
/// \effects Sets the cv- and ref-qualifier.
|
||||
void cv_ref_qualifier(cpp_cv cv, cpp_reference ref) noexcept
|
||||
{
|
||||
auto& base = static_cast<cpp_member_function_base&>(*this->function);
|
||||
base.cv_ = cv;
|
||||
base.ref_ = ref;
|
||||
}
|
||||
|
||||
/// \effects Sets the `virtual`-ness of the function.
|
||||
void virtual_info(type_safe::flag_set<cpp_virtual_flags> virt) noexcept
|
||||
{
|
||||
static_cast<cpp_member_function_base&>(*this->function).virtual_ = virt;
|
||||
}
|
||||
|
||||
/// \effects Marks the function as `constexpr`.
|
||||
void is_constexpr() noexcept
|
||||
{
|
||||
static_cast<cpp_member_function_base&>(*this->function).constexpr_ = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
basic_member_builder() noexcept = default;
|
||||
};
|
||||
|
||||
/// \effects Sets name and return type, as well as the rest to defaults.
|
||||
cpp_member_function_base(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
: cpp_function_base(std::move(name)),
|
||||
return_type_(std::move(return_type)),
|
||||
cv_(cpp_cv_none),
|
||||
ref_(cpp_ref_none),
|
||||
constexpr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string do_get_signature() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
cpp_virtual virtual_;
|
||||
cpp_cv cv_;
|
||||
cpp_reference ref_;
|
||||
bool constexpr_;
|
||||
basic_member_builder() noexcept = default;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a member function.
|
||||
class cpp_member_function final : public cpp_member_function_base
|
||||
/// \effects Sets name and return type, as well as the rest to defaults.
|
||||
cpp_member_function_base(std::string name, std::unique_ptr<cpp_type> return_type)
|
||||
: cpp_function_base(std::move(name)), return_type_(std::move(return_type)), cv_(cpp_cv_none),
|
||||
ref_(cpp_ref_none), constexpr_(false)
|
||||
{}
|
||||
|
||||
protected:
|
||||
std::string do_get_signature() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_type> return_type_;
|
||||
cpp_virtual virtual_;
|
||||
cpp_cv cv_;
|
||||
cpp_reference ref_;
|
||||
bool constexpr_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a member function.
|
||||
class cpp_member_function final : public cpp_member_function_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_member_function]().
|
||||
class builder : public cpp_member_function_base::basic_member_builder<cpp_member_function>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_member_function]().
|
||||
class builder : public cpp_member_function_base::basic_member_builder<cpp_member_function>
|
||||
{
|
||||
public:
|
||||
using cpp_member_function_base::basic_member_builder<
|
||||
cpp_member_function>::basic_member_builder;
|
||||
};
|
||||
|
||||
private:
|
||||
using cpp_member_function_base::cpp_member_function_base;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_member_builder<cpp_member_function>;
|
||||
using cpp_member_function_base::basic_member_builder<
|
||||
cpp_member_function>::basic_member_builder;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ conversion operator.
|
||||
class cpp_conversion_op final : public cpp_member_function_base
|
||||
private:
|
||||
using cpp_member_function_base::cpp_member_function_base;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_member_builder<cpp_member_function>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ conversion operator.
|
||||
class cpp_conversion_op final : public cpp_member_function_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_conversion_op]().
|
||||
class builder : public basic_member_builder<cpp_conversion_op>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
using basic_member_builder::basic_member_builder;
|
||||
|
||||
/// Builder for [cppast::cpp_conversion_op]().
|
||||
class builder : public basic_member_builder<cpp_conversion_op>
|
||||
/// \effects Marks the conversion operator `explicit`.
|
||||
void is_explicit() noexcept
|
||||
{
|
||||
public:
|
||||
using basic_member_builder::basic_member_builder;
|
||||
|
||||
/// \effects Marks the conversion operator `explicit`.
|
||||
void is_explicit() noexcept
|
||||
{
|
||||
function->explicit_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
using basic_member_builder::add_parameter;
|
||||
using basic_member_builder::is_variadic;
|
||||
};
|
||||
|
||||
/// \returns Whether or not the conversion is `explicit`.
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return explicit_;
|
||||
function->explicit_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_conversion_op(std::string name, std::unique_ptr<cpp_type> return_t)
|
||||
: cpp_member_function_base(std::move(name), std::move(return_t)), explicit_(false)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
bool explicit_;
|
||||
|
||||
friend basic_member_builder<cpp_conversion_op>;
|
||||
using basic_member_builder::add_parameter;
|
||||
using basic_member_builder::is_variadic;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ constructor.
|
||||
class cpp_constructor final : public cpp_function_base
|
||||
/// \returns Whether or not the conversion is `explicit`.
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return explicit_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_conversion_op(std::string name, std::unique_ptr<cpp_type> return_t)
|
||||
: cpp_member_function_base(std::move(name), std::move(return_t)), explicit_(false)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
bool explicit_;
|
||||
|
||||
friend basic_member_builder<cpp_conversion_op>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ constructor.
|
||||
class cpp_constructor final : public cpp_function_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_constructor]().
|
||||
class builder : public basic_builder<cpp_constructor>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
using basic_builder::basic_builder;
|
||||
|
||||
/// Builder for [cppast::cpp_constructor]().
|
||||
class builder : public basic_builder<cpp_constructor>
|
||||
/// \effects Marks the constructor `explicit`.
|
||||
void is_explicit() noexcept
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
|
||||
/// \effects Marks the constructor `explicit`.
|
||||
void is_explicit() noexcept
|
||||
{
|
||||
function->explicit_ = true;
|
||||
}
|
||||
|
||||
/// \effects Marks the constructor `constexpr`.
|
||||
void is_constexpr() noexcept
|
||||
{
|
||||
function->constexpr_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
/// \returns Whether or not the constructor is `explicit`.
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return explicit_;
|
||||
function->explicit_ = true;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the constructor is `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
/// \effects Marks the constructor `constexpr`.
|
||||
void is_constexpr() noexcept
|
||||
{
|
||||
return constexpr_;
|
||||
function->constexpr_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_constructor(std::string name)
|
||||
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
bool explicit_;
|
||||
bool constexpr_;
|
||||
|
||||
friend basic_builder<cpp_constructor>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ destructor.
|
||||
class cpp_destructor final : public cpp_function_base
|
||||
/// \returns Whether or not the constructor is `explicit`.
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return explicit_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the constructor is `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return constexpr_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_constructor(std::string name)
|
||||
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
bool explicit_;
|
||||
bool constexpr_;
|
||||
|
||||
friend basic_builder<cpp_constructor>;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ destructor.
|
||||
class cpp_destructor final : public cpp_function_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_destructor]().
|
||||
class builder : public basic_builder<cpp_destructor>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
using basic_builder::basic_builder;
|
||||
|
||||
/// Builds a [cppast::cpp_destructor]().
|
||||
class builder : public basic_builder<cpp_destructor>
|
||||
/// \effects Sets the `virtual`-ness of the destructor.
|
||||
void virtual_info(cpp_virtual virt) noexcept
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
|
||||
/// \effects Sets the `virtual`-ness of the destructor.
|
||||
void virtual_info(cpp_virtual virt) noexcept
|
||||
{
|
||||
function->virtual_ = virt;
|
||||
}
|
||||
|
||||
private:
|
||||
using basic_builder::add_parameter;
|
||||
using basic_builder::is_variadic;
|
||||
};
|
||||
|
||||
/// \returns Whether or not it is `virtual`.
|
||||
bool is_virtual() const noexcept
|
||||
{
|
||||
return virtual_info().has_value();
|
||||
}
|
||||
|
||||
/// \returns The `virtual`-ness of the constructor.
|
||||
cpp_virtual virtual_info() const noexcept
|
||||
{
|
||||
return virtual_;
|
||||
function->virtual_ = virt;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_destructor(std::string name) : cpp_function_base(std::move(name)) {}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_virtual virtual_;
|
||||
|
||||
friend basic_builder<cpp_destructor>;
|
||||
using basic_builder::add_parameter;
|
||||
using basic_builder::is_variadic;
|
||||
};
|
||||
|
||||
/// \returns Whether or not it is `virtual`.
|
||||
bool is_virtual() const noexcept
|
||||
{
|
||||
return virtual_info().has_value();
|
||||
}
|
||||
|
||||
/// \returns The `virtual`-ness of the constructor.
|
||||
cpp_virtual virtual_info() const noexcept
|
||||
{
|
||||
return virtual_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_destructor(std::string name) : cpp_function_base(std::move(name)) {}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_virtual virtual_;
|
||||
|
||||
friend basic_builder<cpp_destructor>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,84 +10,81 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Base class for all kinds of member variables.
|
||||
class cpp_member_variable_base : public cpp_entity, public cpp_variable_base
|
||||
/// Base class for all kinds of member variables.
|
||||
class cpp_member_variable_base : public cpp_entity, public cpp_variable_base
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the member variable is declared `mutable`.
|
||||
bool is_mutable() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the member variable is declared `mutable`.
|
||||
bool is_mutable() const noexcept
|
||||
{
|
||||
return mutable_;
|
||||
}
|
||||
return mutable_;
|
||||
}
|
||||
|
||||
protected:
|
||||
cpp_member_variable_base(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def, bool is_mutable)
|
||||
: cpp_entity(std::move(name)),
|
||||
cpp_variable_base(std::move(type), std::move(def)),
|
||||
mutable_(is_mutable)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
cpp_member_variable_base(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def, bool is_mutable)
|
||||
: cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def)),
|
||||
mutable_(is_mutable)
|
||||
{}
|
||||
|
||||
private:
|
||||
bool mutable_;
|
||||
};
|
||||
private:
|
||||
bool mutable_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ member variable.
|
||||
class cpp_member_variable final : public cpp_member_variable_base
|
||||
/// A [cppast::cpp_entity]() modelling a C++ member variable.
|
||||
class cpp_member_variable final : public cpp_member_variable_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered member variable.
|
||||
/// \notes `def` may be `nullptr` in which case there is no member initializer provided.
|
||||
static std::unique_ptr<cpp_member_variable> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name,
|
||||
std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def,
|
||||
bool is_mutable);
|
||||
|
||||
private:
|
||||
using cpp_member_variable_base::cpp_member_variable_base;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ bitfield.
|
||||
class cpp_bitfield final : public cpp_member_variable_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered bitfield.
|
||||
/// \notes It cannot have a member initializer, i.e. default value.
|
||||
static std::unique_ptr<cpp_bitfield> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, std::unique_ptr<cpp_type> type,
|
||||
unsigned no_bits, bool is_mutable);
|
||||
|
||||
/// \returns A newly created unnamed bitfield.
|
||||
/// \notes It will not be registered, as it is unnamed.
|
||||
static std::unique_ptr<cpp_bitfield> build(std::unique_ptr<cpp_type> type, unsigned no_bits,
|
||||
bool is_mutable);
|
||||
|
||||
/// \returns The number of bits of the bitfield.
|
||||
unsigned no_bits() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return bits_;
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered member variable.
|
||||
/// \notes `def` may be `nullptr` in which case there is no member initializer provided.
|
||||
static std::unique_ptr<cpp_member_variable> build(const cpp_entity_index& idx,
|
||||
cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def,
|
||||
bool is_mutable);
|
||||
private:
|
||||
cpp_bitfield(std::string name, std::unique_ptr<cpp_type> type, unsigned no_bits,
|
||||
bool is_mutable)
|
||||
: cpp_member_variable_base(std::move(name), std::move(type), nullptr, is_mutable),
|
||||
bits_(no_bits)
|
||||
{}
|
||||
|
||||
private:
|
||||
using cpp_member_variable_base::cpp_member_variable_base;
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ bitfield.
|
||||
class cpp_bitfield final : public cpp_member_variable_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered bitfield.
|
||||
/// \notes It cannot have a member initializer, i.e. default value.
|
||||
static std::unique_ptr<cpp_bitfield> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, std::unique_ptr<cpp_type> type,
|
||||
unsigned no_bits, bool is_mutable);
|
||||
|
||||
/// \returns A newly created unnamed bitfield.
|
||||
/// \notes It will not be registered, as it is unnamed.
|
||||
static std::unique_ptr<cpp_bitfield> build(std::unique_ptr<cpp_type> type, unsigned no_bits,
|
||||
bool is_mutable);
|
||||
|
||||
/// \returns The number of bits of the bitfield.
|
||||
unsigned no_bits() const noexcept
|
||||
{
|
||||
return bits_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_bitfield(std::string name, std::unique_ptr<cpp_type> type, unsigned no_bits,
|
||||
bool is_mutable)
|
||||
: cpp_member_variable_base(std::move(name), std::move(type), nullptr, is_mutable),
|
||||
bits_(no_bits)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
unsigned bits_;
|
||||
};
|
||||
unsigned bits_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -7,196 +7,188 @@
|
|||
|
||||
#include <cppast/cpp_entity_container.hpp>
|
||||
#include <cppast/cpp_entity_index.hpp>
|
||||
#include <cppast/cpp_entity_ref.hpp>
|
||||
#include <cppast/cpp_entity_kind.hpp>
|
||||
#include <cppast/cpp_entity_ref.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a namespace.
|
||||
class cpp_namespace final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_namespace, cpp_entity>
|
||||
/// A [cppast::cpp_entity]() modelling a namespace.
|
||||
class cpp_namespace final : public cpp_entity,
|
||||
public cpp_entity_container<cpp_namespace, cpp_entity>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_namespace]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Sets the namespace name and whether it is inline and nested.
|
||||
explicit builder(std::string name, bool is_inline, bool is_nested)
|
||||
: namespace_(new cpp_namespace(std::move(name), is_inline, is_nested))
|
||||
{}
|
||||
|
||||
/// Builds a [cppast::cpp_namespace]().
|
||||
class builder
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the namespace name and whether it is inline and nested.
|
||||
explicit builder(std::string name, bool is_inline, bool is_nested)
|
||||
: namespace_(new cpp_namespace(std::move(name), is_inline, is_nested))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Adds an entity.
|
||||
void add_child(std::unique_ptr<cpp_entity> child) noexcept
|
||||
{
|
||||
namespace_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished namespace.
|
||||
cpp_namespace& get() const noexcept
|
||||
{
|
||||
return *namespace_;
|
||||
}
|
||||
|
||||
/// \effects Registers the namespace in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished namespace.
|
||||
std::unique_ptr<cpp_namespace> finish(const cpp_entity_index& idx, cpp_entity_id id)
|
||||
{
|
||||
idx.register_namespace(std::move(id), type_safe::ref(*namespace_));
|
||||
return std::move(namespace_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_namespace> namespace_;
|
||||
};
|
||||
|
||||
/// \returns Whether or not the namespace is an `inline namespace`.
|
||||
bool is_inline() const noexcept
|
||||
{
|
||||
return inline_;
|
||||
namespace_->add_child(std::move(child));
|
||||
}
|
||||
|
||||
/// \returns Whether or not the namespace is part of a C++17 nested namespace.
|
||||
bool is_nested() const noexcept
|
||||
/// \returns The not yet finished namespace.
|
||||
cpp_namespace& get() const noexcept
|
||||
{
|
||||
return nested_;
|
||||
return *namespace_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the namespace is anonymous.
|
||||
bool is_anonymous() const noexcept
|
||||
/// \effects Registers the namespace in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished namespace.
|
||||
std::unique_ptr<cpp_namespace> finish(const cpp_entity_index& idx, cpp_entity_id id)
|
||||
{
|
||||
return name().empty();
|
||||
idx.register_namespace(std::move(id), type_safe::ref(*namespace_));
|
||||
return std::move(namespace_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_namespace(std::string name, bool is_inline, bool is_nested)
|
||||
: cpp_entity(std::move(name)), inline_(is_inline), nested_(is_nested)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return type_safe::ref(*this);
|
||||
}
|
||||
|
||||
bool inline_;
|
||||
bool nested_;
|
||||
std::unique_ptr<cpp_namespace> namespace_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// \returns Whether or not the namespace is an `inline namespace`.
|
||||
bool is_inline() const noexcept
|
||||
{
|
||||
struct cpp_namespace_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
return inline_;
|
||||
}
|
||||
|
||||
/// A reference to a [cppast::cpp_namespace]().
|
||||
using cpp_namespace_ref =
|
||||
basic_cpp_entity_ref<cpp_namespace, detail::cpp_namespace_ref_predicate>;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a namespace alias.
|
||||
class cpp_namespace_alias final : public cpp_entity
|
||||
/// \returns Whether or not the namespace is part of a C++17 nested namespace.
|
||||
bool is_nested() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return nested_;
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered namespace alias.
|
||||
static std::unique_ptr<cpp_namespace_alias> build(const cpp_entity_index& idx,
|
||||
cpp_entity_id id, std::string name,
|
||||
cpp_namespace_ref target);
|
||||
/// \returns Whether or not the namespace is anonymous.
|
||||
bool is_anonymous() const noexcept
|
||||
{
|
||||
return name().empty();
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_namespace_ref]() to the aliased namespace.
|
||||
/// \notes If the namespace aliases aliases another namespace alias,
|
||||
/// the target entity will still be the namespace, not the alias.
|
||||
const cpp_namespace_ref& target() const noexcept
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
private:
|
||||
cpp_namespace(std::string name, bool is_inline, bool is_nested)
|
||||
: cpp_entity(std::move(name)), inline_(is_inline), nested_(is_nested)
|
||||
{}
|
||||
|
||||
private:
|
||||
cpp_namespace_alias(std::string name, cpp_namespace_ref target)
|
||||
: cpp_entity(std::move(name)), target_(std::move(target))
|
||||
{
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
type_safe::optional<cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return type_safe::ref(*this);
|
||||
}
|
||||
|
||||
cpp_namespace_ref target_;
|
||||
bool inline_;
|
||||
bool nested_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_namespace_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a using directive.
|
||||
///
|
||||
/// A using directive is `using namespace std`, for example.
|
||||
/// \notes It does not have a name.
|
||||
class cpp_using_directive final : public cpp_entity
|
||||
/// A reference to a [cppast::cpp_namespace]().
|
||||
using cpp_namespace_ref = basic_cpp_entity_ref<cpp_namespace, detail::cpp_namespace_ref_predicate>;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a namespace alias.
|
||||
class cpp_namespace_alias final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered namespace alias.
|
||||
static std::unique_ptr<cpp_namespace_alias> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, cpp_namespace_ref target);
|
||||
|
||||
/// \returns The [cppast::cpp_namespace_ref]() to the aliased namespace.
|
||||
/// \notes If the namespace aliases aliases another namespace alias,
|
||||
/// the target entity will still be the namespace, not the alias.
|
||||
const cpp_namespace_ref& target() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return target_;
|
||||
}
|
||||
|
||||
/// \returns A newly created using directive.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_using_directive> build(cpp_namespace_ref target)
|
||||
{
|
||||
return std::unique_ptr<cpp_using_directive>(new cpp_using_directive(std::move(target)));
|
||||
}
|
||||
private:
|
||||
cpp_namespace_alias(std::string name, cpp_namespace_ref target)
|
||||
: cpp_entity(std::move(name)), target_(std::move(target))
|
||||
{}
|
||||
|
||||
/// \returns The [cppast::cpp_namespace_ref]() that is being used.
|
||||
const cpp_namespace_ref& target() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
private:
|
||||
cpp_using_directive(cpp_namespace_ref target) : cpp_entity(""), target_(std::move(target))
|
||||
{
|
||||
}
|
||||
cpp_namespace_ref target_;
|
||||
};
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
/// A [cppast::cpp_entity]() modelling a using directive.
|
||||
///
|
||||
/// A using directive is `using namespace std`, for example.
|
||||
/// \notes It does not have a name.
|
||||
class cpp_using_directive final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
cpp_namespace_ref target_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a using declaration.
|
||||
///
|
||||
/// A using declaration is `using std::vector`, for example.
|
||||
/// \notes It does not have a name.
|
||||
class cpp_using_declaration final : public cpp_entity
|
||||
/// \returns A newly created using directive.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_using_directive> build(cpp_namespace_ref target)
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return std::unique_ptr<cpp_using_directive>(new cpp_using_directive(std::move(target)));
|
||||
}
|
||||
|
||||
/// \returns A newly created using declaration.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_using_declaration> build(cpp_entity_ref target)
|
||||
{
|
||||
return std::unique_ptr<cpp_using_declaration>(
|
||||
new cpp_using_declaration(std::move(target)));
|
||||
}
|
||||
/// \returns The [cppast::cpp_namespace_ref]() that is being used.
|
||||
const cpp_namespace_ref& target() const
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_entity_ref]() that is being used.
|
||||
/// \notes The name of the reference is the same as the name of this entity.
|
||||
const cpp_entity_ref& target() const noexcept
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
private:
|
||||
cpp_using_directive(cpp_namespace_ref target) : cpp_entity(""), target_(std::move(target)) {}
|
||||
|
||||
private:
|
||||
cpp_using_declaration(cpp_entity_ref target) : cpp_entity(""), target_(std::move(target)) {}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
cpp_namespace_ref target_;
|
||||
};
|
||||
|
||||
cpp_entity_ref target_;
|
||||
};
|
||||
/// A [cppast::cpp_entity]() modelling a using declaration.
|
||||
///
|
||||
/// A using declaration is `using std::vector`, for example.
|
||||
/// \notes It does not have a name.
|
||||
class cpp_using_declaration final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created using declaration.
|
||||
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
|
||||
/// as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_using_declaration> build(cpp_entity_ref target)
|
||||
{
|
||||
return std::unique_ptr<cpp_using_declaration>(new cpp_using_declaration(std::move(target)));
|
||||
}
|
||||
|
||||
/// \returns The [cppast::cpp_entity_ref]() that is being used.
|
||||
/// \notes The name of the reference is the same as the name of this entity.
|
||||
const cpp_entity_ref& target() const noexcept
|
||||
{
|
||||
return target_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_using_declaration(cpp_entity_ref target) : cpp_entity(""), target_(std::move(target)) {}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_ref target_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_NAMESPACE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -12,197 +12,194 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a macro parameter.
|
||||
class cpp_macro_parameter final : public cpp_entity
|
||||
/// A [cppast::cpp_entity]() modelling a macro parameter.
|
||||
class cpp_macro_parameter final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly built macro parameter.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index]() as no other
|
||||
/// [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_macro_parameter> build(std::string name)
|
||||
{
|
||||
return std::unique_ptr<cpp_macro_parameter>(new cpp_macro_parameter(std::move(name)));
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_macro_parameter(std::string name) : cpp_entity(std::move(name)) {}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a macro definition.
|
||||
class cpp_macro_definition final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly built object like macro.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_macro_definition> build_object_like(std::string name,
|
||||
std::string replacement)
|
||||
{
|
||||
std::unique_ptr<cpp_macro_definition> result{new cpp_macro_definition(std::move(name))};
|
||||
result->replacement_ = std::move(replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Builds a function like macro.
|
||||
class function_like_builder
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly built macro parameter.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index]() as no other [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_macro_parameter> build(std::string name)
|
||||
/// \effects Sets the name of the function like macro.
|
||||
function_like_builder(std::string name) : result_(new cpp_macro_definition(std::move(name)))
|
||||
{
|
||||
return std::unique_ptr<cpp_macro_parameter>(new cpp_macro_parameter(std::move(name)));
|
||||
result_->kind_ = function_like;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_macro_parameter(std::string name) : cpp_entity(std::move(name)) {}
|
||||
/// \effects Sets the replacement text.
|
||||
void replacement(std::string replacement)
|
||||
{
|
||||
result_->replacement_ = std::move(replacement);
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
/// \effects Marks the macro as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
result_->kind_ = variadic_function;
|
||||
}
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a macro definition.
|
||||
class cpp_macro_definition final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
/// \effects Adds a parameter.
|
||||
/// \group param
|
||||
void parameter(std::unique_ptr<cpp_macro_parameter> param)
|
||||
{
|
||||
result_->parameters_.push_back(*result_, std::move(param));
|
||||
}
|
||||
/// \group param
|
||||
void parameter(std::string name)
|
||||
{
|
||||
parameter(cpp_macro_parameter::build(std::move(name)));
|
||||
}
|
||||
|
||||
/// \returns A newly built object like macro.
|
||||
/// \returns The finished macro.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_macro_definition> build_object_like(std::string name,
|
||||
std::string replacement)
|
||||
std::unique_ptr<cpp_macro_definition> finish()
|
||||
{
|
||||
std::unique_ptr<cpp_macro_definition> result{new cpp_macro_definition(std::move(name))};
|
||||
result->replacement_ = std::move(replacement);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Builds a function like macro.
|
||||
class function_like_builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name of the function like macro.
|
||||
function_like_builder(std::string name)
|
||||
: result_(new cpp_macro_definition(std::move(name)))
|
||||
{
|
||||
result_->kind_ = function_like;
|
||||
}
|
||||
|
||||
/// \effects Sets the replacement text.
|
||||
void replacement(std::string replacement)
|
||||
{
|
||||
result_->replacement_ = std::move(replacement);
|
||||
}
|
||||
|
||||
/// \effects Marks the macro as variadic.
|
||||
void is_variadic()
|
||||
{
|
||||
result_->kind_ = variadic_function;
|
||||
}
|
||||
|
||||
/// \effects Adds a parameter.
|
||||
/// \group param
|
||||
void parameter(std::unique_ptr<cpp_macro_parameter> param)
|
||||
{
|
||||
result_->parameters_.push_back(*result_, std::move(param));
|
||||
}
|
||||
/// \group param
|
||||
void parameter(std::string name)
|
||||
{
|
||||
parameter(cpp_macro_parameter::build(std::move(name)));
|
||||
}
|
||||
|
||||
/// \returns The finished macro.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||
std::unique_ptr<cpp_macro_definition> finish()
|
||||
{
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_macro_definition> result_;
|
||||
};
|
||||
|
||||
/// \returns The replacement text of the macro.
|
||||
const std::string& replacement() const noexcept
|
||||
{
|
||||
return replacement_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is an object like macro.
|
||||
bool is_object_like() const noexcept
|
||||
{
|
||||
return kind_ == object_like;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is a function like macro.
|
||||
bool is_function_like() const noexcept
|
||||
{
|
||||
return kind_ != object_like;
|
||||
}
|
||||
|
||||
/// \returns Whether or not it is a variadic macro.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return kind_ == variadic_function;
|
||||
}
|
||||
|
||||
/// \returns The parameters of the macro.
|
||||
/// \notes It has none if it is not a function like macro.
|
||||
detail::iteratable_intrusive_list<cpp_macro_parameter> parameters() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_macro_definition(std::string name) : cpp_entity(std::move(name)), kind_(object_like) {}
|
||||
|
||||
detail::intrusive_list<cpp_macro_parameter> parameters_;
|
||||
std::string replacement_;
|
||||
|
||||
enum : char
|
||||
{
|
||||
object_like,
|
||||
function_like,
|
||||
variadic_function,
|
||||
} kind_;
|
||||
|
||||
friend function_like_builder;
|
||||
std::unique_ptr<cpp_macro_definition> result_;
|
||||
};
|
||||
|
||||
/// The kind of [cppast::cpp_include_directive]().
|
||||
enum class cpp_include_kind
|
||||
/// \returns The replacement text of the macro.
|
||||
const std::string& replacement() const noexcept
|
||||
{
|
||||
system, //< An `#include <...>`.
|
||||
local, //< An `#include "..."`.
|
||||
};
|
||||
return replacement_;
|
||||
}
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling an `#include`.
|
||||
class cpp_include_directive final : public cpp_entity
|
||||
/// \returns Whether or not it is an object like macro.
|
||||
bool is_object_like() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return kind_ == object_like;
|
||||
}
|
||||
|
||||
/// \returns A newly built include directive.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_include_directive> build(const cpp_file_ref& target,
|
||||
cpp_include_kind kind,
|
||||
std::string full_path)
|
||||
{
|
||||
return std::unique_ptr<cpp_include_directive>(
|
||||
new cpp_include_directive(target, kind, std::move(full_path)));
|
||||
}
|
||||
/// \returns Whether or not it is a function like macro.
|
||||
bool is_function_like() const noexcept
|
||||
{
|
||||
return kind_ != object_like;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_file]() it includes.
|
||||
cpp_file_ref target() const noexcept
|
||||
{
|
||||
return cpp_file_ref(target_, name());
|
||||
}
|
||||
/// \returns Whether or not it is a variadic macro.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return kind_ == variadic_function;
|
||||
}
|
||||
|
||||
/// \returns The kind of include it is.
|
||||
cpp_include_kind include_kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
/// \returns The parameters of the macro.
|
||||
/// \notes It has none if it is not a function like macro.
|
||||
detail::iteratable_intrusive_list<cpp_macro_parameter> parameters() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns The full path of the included file.
|
||||
const std::string& full_path() const noexcept
|
||||
{
|
||||
return full_path_;
|
||||
}
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
cpp_macro_definition(std::string name) : cpp_entity(std::move(name)), kind_(object_like) {}
|
||||
|
||||
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind,
|
||||
std::string full_path)
|
||||
: cpp_entity(target.name()),
|
||||
target_(target.id()[0u]),
|
||||
kind_(kind),
|
||||
full_path_(std::move(full_path))
|
||||
{
|
||||
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
|
||||
}
|
||||
detail::intrusive_list<cpp_macro_parameter> parameters_;
|
||||
std::string replacement_;
|
||||
|
||||
cpp_entity_id target_;
|
||||
cpp_include_kind kind_;
|
||||
std::string full_path_;
|
||||
};
|
||||
enum : char
|
||||
{
|
||||
object_like,
|
||||
function_like,
|
||||
variadic_function,
|
||||
} kind_;
|
||||
|
||||
friend function_like_builder;
|
||||
};
|
||||
|
||||
/// The kind of [cppast::cpp_include_directive]().
|
||||
enum class cpp_include_kind
|
||||
{
|
||||
system, //< An `#include <...>`.
|
||||
local, //< An `#include "..."`.
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling an `#include`.
|
||||
class cpp_include_directive final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly built include directive.
|
||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||
static std::unique_ptr<cpp_include_directive> build(const cpp_file_ref& target,
|
||||
cpp_include_kind kind,
|
||||
std::string full_path)
|
||||
{
|
||||
return std::unique_ptr<cpp_include_directive>(
|
||||
new cpp_include_directive(target, kind, std::move(full_path)));
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_file]() it includes.
|
||||
cpp_file_ref target() const noexcept
|
||||
{
|
||||
return cpp_file_ref(target_, name());
|
||||
}
|
||||
|
||||
/// \returns The kind of include it is.
|
||||
cpp_include_kind include_kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
/// \returns The full path of the included file.
|
||||
const std::string& full_path() const noexcept
|
||||
{
|
||||
return full_path_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind, std::string full_path)
|
||||
: cpp_entity(target.name()), target_(target.id()[0u]), kind_(kind),
|
||||
full_path_(std::move(full_path))
|
||||
{
|
||||
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
|
||||
}
|
||||
|
||||
cpp_entity_id target_;
|
||||
cpp_include_kind kind_;
|
||||
std::string full_path_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_PREPROCESSOR_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,43 +10,42 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_static_assert : public cpp_entity
|
||||
class cpp_static_assert : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created `static_assert()` entity.
|
||||
/// \notes It will not be registered as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_static_assert> build(std::unique_ptr<cpp_expression> expr,
|
||||
std::string msg)
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return std::unique_ptr<cpp_static_assert>(
|
||||
new cpp_static_assert(std::move(expr), std::move(msg)));
|
||||
}
|
||||
|
||||
/// \returns A newly created `static_assert()` entity.
|
||||
/// \notes It will not be registered as nothing can refer to it.
|
||||
static std::unique_ptr<cpp_static_assert> build(std::unique_ptr<cpp_expression> expr,
|
||||
std::string msg)
|
||||
{
|
||||
return std::unique_ptr<cpp_static_assert>(
|
||||
new cpp_static_assert(std::move(expr), std::move(msg)));
|
||||
}
|
||||
/// \returns A reference to the [cppast::cpp_expression]() that is being asserted.
|
||||
const cpp_expression& expression() const noexcept
|
||||
{
|
||||
return *expr_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_expression]() that is being asserted.
|
||||
const cpp_expression& expression() const noexcept
|
||||
{
|
||||
return *expr_;
|
||||
}
|
||||
/// \returns A reference to the message of the assertion.
|
||||
const std::string& message() const noexcept
|
||||
{
|
||||
return msg_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the message of the assertion.
|
||||
const std::string& message() const noexcept
|
||||
{
|
||||
return msg_;
|
||||
}
|
||||
private:
|
||||
cpp_static_assert(std::unique_ptr<cpp_expression> expr, std::string msg)
|
||||
: cpp_entity(""), expr_(std::move(expr)), msg_(std::move(msg))
|
||||
{}
|
||||
|
||||
private:
|
||||
cpp_static_assert(std::unique_ptr<cpp_expression> expr, std::string msg)
|
||||
: cpp_entity(""), expr_(std::move(expr)), msg_(std::move(msg))
|
||||
{
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_expression> expr_;
|
||||
std::string msg_;
|
||||
};
|
||||
std::unique_ptr<cpp_expression> expr_;
|
||||
std::string msg_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_STATIC_ASSERT_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -7,49 +7,47 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// C++ storage class specifiers.
|
||||
///
|
||||
/// See http://en.cppreference.com/w/cpp/language/storage_duration, for example.
|
||||
/// \notes These are just all the possible *keywords* used in a variable declaration,
|
||||
/// not necessarily their *semantic* meaning.
|
||||
enum cpp_storage_class_specifiers : int
|
||||
{
|
||||
cpp_storage_class_none = 0, //< no storage class specifier given.
|
||||
/// C++ storage class specifiers.
|
||||
///
|
||||
/// See http://en.cppreference.com/w/cpp/language/storage_duration, for example.
|
||||
/// \notes These are just all the possible *keywords* used in a variable declaration,
|
||||
/// not necessarily their *semantic* meaning.
|
||||
enum cpp_storage_class_specifiers : int
|
||||
{
|
||||
cpp_storage_class_none = 0, //< no storage class specifier given.
|
||||
|
||||
cpp_storage_class_auto = 1, //< *automatic* storage duration.
|
||||
cpp_storage_class_auto = 1, //< *automatic* storage duration.
|
||||
|
||||
cpp_storage_class_static =
|
||||
2, //< *static* or *thread* storage duration and *internal* linkage.
|
||||
cpp_storage_class_extern =
|
||||
4, //< *static* or *thread* storage duration and *external* linkage.
|
||||
cpp_storage_class_static = 2, //< *static* or *thread* storage duration and *internal* linkage.
|
||||
cpp_storage_class_extern = 4, //< *static* or *thread* storage duration and *external* linkage.
|
||||
|
||||
cpp_storage_class_thread_local = 8, //< *thread* storage duration.
|
||||
/// \notes This is the only one that can be combined with the others.
|
||||
};
|
||||
cpp_storage_class_thread_local = 8, //< *thread* storage duration.
|
||||
/// \notes This is the only one that can be combined with the others.
|
||||
};
|
||||
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `thread_local`.
|
||||
inline bool is_thread_local(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_thread_local) != 0;
|
||||
}
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `thread_local`.
|
||||
inline bool is_thread_local(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_thread_local) != 0;
|
||||
}
|
||||
|
||||
/// \returns Whether the [cppast::cpp_storage_class_speicifers]() contain `auto`.
|
||||
inline bool is_auto(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_auto) != 0;
|
||||
}
|
||||
/// \returns Whether the [cppast::cpp_storage_class_speicifers]() contain `auto`.
|
||||
inline bool is_auto(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_auto) != 0;
|
||||
}
|
||||
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `static`.
|
||||
inline bool is_static(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_static) != 0;
|
||||
}
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `static`.
|
||||
inline bool is_static(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_static) != 0;
|
||||
}
|
||||
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `extern`.
|
||||
inline bool is_extern(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_extern) != 0;
|
||||
}
|
||||
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `extern`.
|
||||
inline bool is_extern(cpp_storage_class_specifiers spec) noexcept
|
||||
{
|
||||
return (spec & cpp_storage_class_extern) != 0;
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_STORAGE_CLASS_SPECIFIERS_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -11,275 +11,263 @@
|
|||
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_entity_container.hpp>
|
||||
#include <cppast/cpp_token.hpp>
|
||||
#include <cppast/cpp_template_parameter.hpp>
|
||||
#include <cppast/cpp_token.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// Base class for all entities modelling a C++ template of some kind.
|
||||
/// Base class for all entities modelling a C++ template of some kind.
|
||||
///
|
||||
/// It is a container of a single [cppast::cpp_entity]() that is the entity being templated.
|
||||
class cpp_template : public cpp_entity, public cpp_entity_container<cpp_template, cpp_entity>
|
||||
{
|
||||
public:
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]()
|
||||
/// entities. \notes These may be empty for a full specialization.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for templates.
|
||||
///
|
||||
/// It is a container of a single [cppast::cpp_entity]() that is the entity being templated.
|
||||
class cpp_template : public cpp_entity, public cpp_entity_container<cpp_template, cpp_entity>
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <class T, class EntityT>
|
||||
class basic_builder
|
||||
{
|
||||
public:
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities.
|
||||
/// \notes These may be empty for a full specialization.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
|
||||
/// \effects Sets the entity that is begin templated.
|
||||
basic_builder(std::unique_ptr<EntityT> templ) : template_entity(new T(std::move(templ))) {}
|
||||
|
||||
basic_builder(basic_builder&&) = default;
|
||||
|
||||
/// \effects Adds a parameter.
|
||||
void add_parameter(std::unique_ptr<cpp_template_parameter> parameter)
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
static_cast<cpp_template&>(*template_entity)
|
||||
.parameters_.push_back(*template_entity, std::move(parameter));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished template.
|
||||
T& get() const noexcept
|
||||
{
|
||||
return *template_entity;
|
||||
}
|
||||
|
||||
/// \effects Registers the template.
|
||||
/// \returns The finished template.
|
||||
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id, bool is_definition)
|
||||
{
|
||||
if (is_definition)
|
||||
idx.register_definition(std::move(id), type_safe::cref(*template_entity));
|
||||
else
|
||||
idx.register_forward_declaration(std::move(id), type_safe::cref(*template_entity));
|
||||
return std::move(template_entity);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for templates.
|
||||
///
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <class T, class EntityT>
|
||||
class basic_builder
|
||||
basic_builder() = default;
|
||||
~basic_builder() noexcept = default;
|
||||
|
||||
std::unique_ptr<T> template_entity;
|
||||
};
|
||||
|
||||
/// \effects Sets the entity to be templated.
|
||||
cpp_template(std::unique_ptr<cpp_entity> entity) : cpp_entity(entity->name())
|
||||
{
|
||||
add_child(std::move(entity));
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::optional<cppast::cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return begin()->scope_name()
|
||||
? type_safe::make_optional(cppast::cpp_scope_name(type_safe::ref(*this)))
|
||||
: type_safe::nullopt;
|
||||
}
|
||||
|
||||
detail::intrusive_list<cpp_template_parameter> parameters_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() representing an instantiation of a [cppast::cpp_template]().
|
||||
class cpp_template_instantiation_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_template_instantiation]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the primary template being instantiated.
|
||||
builder(cpp_template_ref templ)
|
||||
: result_(new cpp_template_instantiation_type(std::move(templ)))
|
||||
{}
|
||||
|
||||
/// \effects Adds the next argument.
|
||||
/// \requires No call to `add_unexposed_arguments()` has happened before.
|
||||
void add_argument(cpp_template_argument arg)
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the entity that is begin templated.
|
||||
basic_builder(std::unique_ptr<EntityT> templ) : template_entity(new T(std::move(templ)))
|
||||
{
|
||||
}
|
||||
result_->arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
|
||||
.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
basic_builder(basic_builder&&) = default;
|
||||
|
||||
/// \effects Adds a parameter.
|
||||
void add_parameter(std::unique_ptr<cpp_template_parameter> parameter)
|
||||
{
|
||||
static_cast<cpp_template&>(*template_entity)
|
||||
.parameters_.push_back(*template_entity, std::move(parameter));
|
||||
}
|
||||
|
||||
/// \returns The not yet finished template.
|
||||
T& get() const noexcept
|
||||
{
|
||||
return *template_entity;
|
||||
}
|
||||
|
||||
/// \effects Registers the template.
|
||||
/// \returns The finished template.
|
||||
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
bool is_definition)
|
||||
{
|
||||
if (is_definition)
|
||||
idx.register_definition(std::move(id), type_safe::cref(*template_entity));
|
||||
else
|
||||
idx.register_forward_declaration(std::move(id),
|
||||
type_safe::cref(*template_entity));
|
||||
return std::move(template_entity);
|
||||
}
|
||||
|
||||
protected:
|
||||
basic_builder() = default;
|
||||
~basic_builder() noexcept = default;
|
||||
|
||||
std::unique_ptr<T> template_entity;
|
||||
};
|
||||
|
||||
/// \effects Sets the entity to be templated.
|
||||
cpp_template(std::unique_ptr<cpp_entity> entity) : cpp_entity(entity->name())
|
||||
/// \effects Adds unexposed arguments as string.
|
||||
void add_unexposed_arguments(std::string arg)
|
||||
{
|
||||
add_child(std::move(entity));
|
||||
result_->arguments_ = std::move(arg);
|
||||
}
|
||||
|
||||
/// \returns The finished instantiation.
|
||||
std::unique_ptr<cpp_template_instantiation_type> finish()
|
||||
{
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::optional<cppast::cpp_scope_name> do_get_scope_name() const override
|
||||
{
|
||||
return begin()->scope_name() ?
|
||||
type_safe::make_optional(cppast::cpp_scope_name(type_safe::ref(*this))) :
|
||||
type_safe::nullopt;
|
||||
}
|
||||
|
||||
detail::intrusive_list<cpp_template_parameter> parameters_;
|
||||
std::unique_ptr<cpp_template_instantiation_type> result_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() representing an instantiation of a [cppast::cpp_template]().
|
||||
class cpp_template_instantiation_type final : public cpp_type
|
||||
/// \returns A reference to the template that is being instantiated.
|
||||
/// \notes It could also point to a specialization,
|
||||
/// this is just the *primary* template.
|
||||
const cpp_template_ref& primary_template() const noexcept
|
||||
{
|
||||
return templ_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the arguments are exposed.
|
||||
bool arguments_exposed() const noexcept
|
||||
{
|
||||
return arguments_.has_value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
}
|
||||
|
||||
/// \returns An array ref to the [cppast::cpp_template_argument](), if there are any.
|
||||
/// \requires The arguments are exposed, i.e. `arguments_exposed()` returns `true`.
|
||||
type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments() const
|
||||
noexcept
|
||||
{
|
||||
auto& vec = arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
if (vec.empty())
|
||||
return type_safe::nullopt;
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
/// \returns The unexposed arguments as string.
|
||||
/// \requires The arguments are not exposed, i.e. `arguments_exposed()` returns `false`.
|
||||
const std::string& unexposed_arguments() const noexcept
|
||||
{
|
||||
return arguments_.value(type_safe::variant_type<std::string>{});
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_instantiation_type(cpp_template_ref ref)
|
||||
: arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
|
||||
templ_(std::move(ref))
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::template_instantiation_t;
|
||||
}
|
||||
|
||||
type_safe::variant<std::vector<cpp_template_argument>, std::string> arguments_;
|
||||
cpp_template_ref templ_;
|
||||
};
|
||||
|
||||
/// Base class for all entities modelling a C++ template specialization.
|
||||
class cpp_template_specialization : public cpp_template
|
||||
{
|
||||
public:
|
||||
/// \returns A reference to the template that is being specialized.
|
||||
cpp_template_ref primary_template() const noexcept
|
||||
{
|
||||
return cpp_template_ref(templ_, name());
|
||||
}
|
||||
|
||||
/// \returns Whether or not the arguments are exposed.
|
||||
bool arguments_exposed() const noexcept
|
||||
{
|
||||
return arguments_.has_value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_argument]()s.
|
||||
/// \requires The arguments are exposed, i.e. `arguments_exposed()` returns `true`.
|
||||
/// \notes For function template specializations it can be empty,
|
||||
/// meaning that the arguments are not explictly given but deduced from the signature.
|
||||
type_safe::array_ref<const cpp_template_argument> arguments() const noexcept
|
||||
{
|
||||
auto& vec = arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
/// \returns The unexposed arguments as string.
|
||||
/// \requires The arguments are not exposed, i.e. `arguments_exposed()` returns `false`.
|
||||
/// \notes For function template specializations it can be empty,
|
||||
/// meaning that the arguments are not explictly given but deduced from the signature.
|
||||
const cpp_token_string& unexposed_arguments() const noexcept
|
||||
{
|
||||
return arguments_.value(type_safe::variant_type<cpp_token_string>{});
|
||||
}
|
||||
|
||||
/// \returns Whether or not the specialization is a full specialization.
|
||||
bool is_full_specialization() const noexcept
|
||||
{
|
||||
// if no template parameters are given, it is a full specialization
|
||||
return parameters().empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for specializations.
|
||||
///
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <class T, class EntityT>
|
||||
class specialization_builder : public basic_builder<T, EntityT>
|
||||
{
|
||||
public:
|
||||
/// Builds a [cppast::cpp_template_instantiation]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the primary template being instantiated.
|
||||
builder(cpp_template_ref templ)
|
||||
: result_(new cpp_template_instantiation_type(std::move(templ)))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Adds the next argument.
|
||||
/// \requires No call to `add_unexposed_arguments()` has happened before.
|
||||
void add_argument(cpp_template_argument arg)
|
||||
{
|
||||
result_->arguments_
|
||||
.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
|
||||
.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
/// \effects Adds unexposed arguments as string.
|
||||
void add_unexposed_arguments(std::string arg)
|
||||
{
|
||||
result_->arguments_ = std::move(arg);
|
||||
}
|
||||
|
||||
/// \returns The finished instantiation.
|
||||
std::unique_ptr<cpp_template_instantiation_type> finish()
|
||||
{
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_template_instantiation_type> result_;
|
||||
};
|
||||
|
||||
/// \returns A reference to the template that is being instantiated.
|
||||
/// \notes It could also point to a specialization,
|
||||
/// this is just the *primary* template.
|
||||
const cpp_template_ref& primary_template() const noexcept
|
||||
{
|
||||
return templ_;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the arguments are exposed.
|
||||
bool arguments_exposed() const noexcept
|
||||
{
|
||||
return arguments_.has_value(
|
||||
type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
}
|
||||
|
||||
/// \returns An array ref to the [cppast::cpp_template_argument](), if there are any.
|
||||
/// \requires The arguments are exposed, i.e. `arguments_exposed()` returns `true`.
|
||||
type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments() const
|
||||
noexcept
|
||||
{
|
||||
auto& vec =
|
||||
arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
if (vec.empty())
|
||||
return type_safe::nullopt;
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
/// \returns The unexposed arguments as string.
|
||||
/// \requires The arguments are not exposed, i.e. `arguments_exposed()` returns `false`.
|
||||
const std::string& unexposed_arguments() const noexcept
|
||||
{
|
||||
return arguments_.value(type_safe::variant_type<std::string>{});
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_instantiation_type(cpp_template_ref ref)
|
||||
: arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
|
||||
templ_(std::move(ref))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::template_instantiation_t;
|
||||
}
|
||||
|
||||
type_safe::variant<std::vector<cpp_template_argument>, std::string> arguments_;
|
||||
cpp_template_ref templ_;
|
||||
};
|
||||
|
||||
/// Base class for all entities modelling a C++ template specialization.
|
||||
class cpp_template_specialization : public cpp_template
|
||||
{
|
||||
public:
|
||||
/// \returns A reference to the template that is being specialized.
|
||||
cpp_template_ref primary_template() const noexcept
|
||||
{
|
||||
return cpp_template_ref(templ_, name());
|
||||
}
|
||||
|
||||
/// \returns Whether or not the arguments are exposed.
|
||||
bool arguments_exposed() const noexcept
|
||||
{
|
||||
return arguments_.has_value(
|
||||
type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over the [cppast::cpp_template_argument]()s.
|
||||
/// \requires The arguments are exposed, i.e. `arguments_exposed()` returns `true`.
|
||||
/// \notes For function template specializations it can be empty,
|
||||
/// meaning that the arguments are not explictly given but deduced from the signature.
|
||||
type_safe::array_ref<const cpp_template_argument> arguments() const noexcept
|
||||
{
|
||||
auto& vec =
|
||||
arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
|
||||
return type_safe::ref(vec.data(), vec.size());
|
||||
}
|
||||
|
||||
/// \returns The unexposed arguments as string.
|
||||
/// \requires The arguments are not exposed, i.e. `arguments_exposed()` returns `false`.
|
||||
/// \notes For function template specializations it can be empty,
|
||||
/// meaning that the arguments are not explictly given but deduced from the signature.
|
||||
const cpp_token_string& unexposed_arguments() const noexcept
|
||||
{
|
||||
return arguments_.value(type_safe::variant_type<cpp_token_string>{});
|
||||
}
|
||||
|
||||
/// \returns Whether or not the specialization is a full specialization.
|
||||
bool is_full_specialization() const noexcept
|
||||
{
|
||||
// if no template parameters are given, it is a full specialization
|
||||
return parameters().empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Builder class for specializations.
|
||||
///
|
||||
/// Inherit from it to provide additional setter.
|
||||
template <class T, class EntityT>
|
||||
class specialization_builder : public basic_builder<T, EntityT>
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the entity that is being templated and the primary template.
|
||||
specialization_builder(std::unique_ptr<EntityT> entity, const cpp_template_ref& templ)
|
||||
{
|
||||
this->template_entity = std::unique_ptr<T>(new T(std::move(entity), templ));
|
||||
}
|
||||
|
||||
/// \effects Adds the next argument for the [cppast::cpp_template_parameter]() of the primary template.
|
||||
/// \requires No call to `add_unexposed_arguments()` has happened before.
|
||||
void add_argument(cpp_template_argument arg)
|
||||
{
|
||||
auto& specialization =
|
||||
static_cast<cpp_template_specialization&>(*this->template_entity);
|
||||
specialization.arguments_
|
||||
.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
|
||||
.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
/// \effects Adds unexposed arguments as string.
|
||||
void add_unexposed_arguments(cpp_token_string arg)
|
||||
{
|
||||
auto& specialization =
|
||||
static_cast<cpp_template_specialization&>(*this->template_entity);
|
||||
specialization.arguments_ = std::move(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
specialization_builder() = default;
|
||||
};
|
||||
|
||||
/// \effects Sets the entity that is being templated and the primary template.
|
||||
cpp_template_specialization(std::unique_ptr<cpp_entity> entity,
|
||||
const cpp_template_ref& templ)
|
||||
: cpp_template(std::move(entity)),
|
||||
arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
|
||||
templ_(templ.id()[0u])
|
||||
specialization_builder(std::unique_ptr<EntityT> entity, const cpp_template_ref& templ)
|
||||
{
|
||||
DEBUG_ASSERT(!templ.is_overloaded()
|
||||
&& (templ.name().empty() || templ.name() == begin()->name()),
|
||||
detail::precondition_error_handler{}, "invalid name of template ref");
|
||||
this->template_entity = std::unique_ptr<T>(new T(std::move(entity), templ));
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::variant<std::vector<cpp_template_argument>, cpp_token_string> arguments_;
|
||||
cpp_entity_id templ_;
|
||||
/// \effects Adds the next argument for the [cppast::cpp_template_parameter]() of the
|
||||
/// primary template. \requires No call to `add_unexposed_arguments()` has happened before.
|
||||
void add_argument(cpp_template_argument arg)
|
||||
{
|
||||
auto& specialization
|
||||
= static_cast<cpp_template_specialization&>(*this->template_entity);
|
||||
specialization.arguments_
|
||||
.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
|
||||
.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
/// \effects Adds unexposed arguments as string.
|
||||
void add_unexposed_arguments(cpp_token_string arg)
|
||||
{
|
||||
auto& specialization
|
||||
= static_cast<cpp_template_specialization&>(*this->template_entity);
|
||||
specialization.arguments_ = std::move(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
specialization_builder() = default;
|
||||
};
|
||||
|
||||
/// \effects Sets the entity that is being templated and the primary template.
|
||||
cpp_template_specialization(std::unique_ptr<cpp_entity> entity, const cpp_template_ref& templ)
|
||||
: cpp_template(std::move(entity)),
|
||||
arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
|
||||
templ_(templ.id()[0u])
|
||||
{
|
||||
DEBUG_ASSERT(!templ.is_overloaded()
|
||||
&& (templ.name().empty() || templ.name() == begin()->name()),
|
||||
detail::precondition_error_handler{}, "invalid name of template ref");
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::variant<std::vector<cpp_template_argument>, cpp_token_string> arguments_;
|
||||
cpp_entity_id templ_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_TEMPLATE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -8,308 +8,295 @@
|
|||
#include <type_safe/optional.hpp>
|
||||
#include <type_safe/variant.hpp>
|
||||
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_variable_base.hpp>
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// Base class for all entities modelling a template parameter of some kind.
|
||||
class cpp_template_parameter : public cpp_entity
|
||||
/// Base class for all entities modelling a template parameter of some kind.
|
||||
class cpp_template_parameter : public cpp_entity
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the parameter is variadic.
|
||||
bool is_variadic() const noexcept
|
||||
{
|
||||
return variadic_;
|
||||
}
|
||||
|
||||
protected:
|
||||
cpp_template_parameter(std::string name, bool variadic)
|
||||
: cpp_entity(std::move(name)), variadic_(variadic)
|
||||
{}
|
||||
|
||||
private:
|
||||
bool variadic_;
|
||||
};
|
||||
|
||||
/// The kind of keyword used in a template parameter.
|
||||
enum class cpp_template_keyword
|
||||
{
|
||||
keyword_class,
|
||||
keyword_typename
|
||||
};
|
||||
|
||||
/// \returns The string associated of the keyword.
|
||||
const char* to_string(cpp_template_keyword kw) noexcept;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ template type parameter.
|
||||
class cpp_template_type_parameter final : public cpp_template_parameter
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered template type parameter.
|
||||
/// \notes The `default_type` may be `nullptr` in which case the parameter has no default.
|
||||
static std::unique_ptr<cpp_template_type_parameter> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name, cpp_template_keyword kw,
|
||||
bool variadic, std::unique_ptr<cpp_type> default_type = nullptr);
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the default type.
|
||||
type_safe::optional_ref<const cpp_type> default_type() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(default_type_.get());
|
||||
}
|
||||
|
||||
/// \returns The keyword used in the template parameter.
|
||||
cpp_template_keyword keyword() const noexcept
|
||||
{
|
||||
return keyword_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_type_parameter(std::string name, cpp_template_keyword kw, bool variadic,
|
||||
std::unique_ptr<cpp_type> default_type)
|
||||
: cpp_template_parameter(std::move(name), variadic), default_type_(std::move(default_type)),
|
||||
keyword_(kw)
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_type> default_type_;
|
||||
cpp_template_keyword keyword_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_template_parameter_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// Reference to a [cppast::cpp_template_type_parameter]().
|
||||
using cpp_template_type_parameter_ref
|
||||
= basic_cpp_entity_ref<cpp_template_type_parameter,
|
||||
detail::cpp_template_parameter_ref_predicate>;
|
||||
|
||||
/// A [cppast::cpp_type]() defined by a [cppast::cpp_template_type_parameter]().
|
||||
class cpp_template_parameter_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created parameter type.
|
||||
static std::unique_ptr<cpp_template_parameter_type> build(
|
||||
cpp_template_type_parameter_ref parameter)
|
||||
{
|
||||
return std::unique_ptr<cpp_template_parameter_type>(
|
||||
new cpp_template_parameter_type(std::move(parameter)));
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_template_type_parameter]() this type refers to.
|
||||
const cpp_template_type_parameter_ref& entity() const noexcept
|
||||
{
|
||||
return parameter_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_parameter_type(cpp_template_type_parameter_ref parameter)
|
||||
: parameter_(std::move(parameter))
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::template_parameter_t;
|
||||
}
|
||||
|
||||
cpp_template_type_parameter_ref parameter_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ non-type template parameter.
|
||||
class cpp_non_type_template_parameter final : public cpp_template_parameter,
|
||||
public cpp_variable_base
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered non type template parameter.
|
||||
/// \notes The `default_value` may be `nullptr` in which case the parameter has no default.
|
||||
static std::unique_ptr<cpp_non_type_template_parameter> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_type> type, bool is_variadic,
|
||||
std::unique_ptr<cpp_expression> default_value = nullptr);
|
||||
|
||||
private:
|
||||
cpp_non_type_template_parameter(std::string name, std::unique_ptr<cpp_type> type, bool variadic,
|
||||
std::unique_ptr<cpp_expression> def)
|
||||
: cpp_template_parameter(std::move(name), variadic),
|
||||
cpp_variable_base(std::move(type), std::move(def))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_template_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
class cpp_template;
|
||||
|
||||
/// A reference to a [cppast::cpp_template]() or a [cppast::cpp_template_template_parameter]().
|
||||
using cpp_template_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_template_ref_predicate>;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ template template parameter.
|
||||
class cpp_template_template_parameter final : public cpp_template_parameter
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_template_template_parameter]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \returns Whether or not the parameter is variadic.
|
||||
bool is_variadic() const noexcept
|
||||
/// \effects Sets the name and whether it is variadic.
|
||||
builder(std::string name, bool variadic)
|
||||
: parameter_(new cpp_template_template_parameter(std::move(name), variadic))
|
||||
{}
|
||||
|
||||
/// \effects Sets the keyword,
|
||||
/// default is [cpp_template_keyword::keyword_class]().
|
||||
void keyword(cpp_template_keyword kw)
|
||||
{
|
||||
return variadic_;
|
||||
parameter_->keyword_ = kw;
|
||||
}
|
||||
|
||||
protected:
|
||||
cpp_template_parameter(std::string name, bool variadic)
|
||||
: cpp_entity(std::move(name)), variadic_(variadic)
|
||||
/// \effects Adds a parameter to the template.
|
||||
void add_parameter(std::unique_ptr<cpp_template_parameter> param)
|
||||
{
|
||||
parameter_->parameters_.push_back(*parameter_, std::move(param));
|
||||
}
|
||||
|
||||
/// \effects Sets the default template.
|
||||
void default_template(cpp_template_ref templ)
|
||||
{
|
||||
parameter_->default_ = std::move(templ);
|
||||
}
|
||||
|
||||
/// \effects Registers the parameter in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished parameter.
|
||||
std::unique_ptr<cpp_template_template_parameter> finish(const cpp_entity_index& idx,
|
||||
cpp_entity_id id)
|
||||
{
|
||||
idx.register_definition(std::move(id), type_safe::ref(*parameter_));
|
||||
return std::move(parameter_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool variadic_;
|
||||
std::unique_ptr<cpp_template_template_parameter> parameter_;
|
||||
};
|
||||
|
||||
/// The kind of keyword used in a template parameter.
|
||||
enum class cpp_template_keyword
|
||||
/// \returns An iteratable object containing the template parameters of the template template
|
||||
/// parameter.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
|
||||
{
|
||||
keyword_class,
|
||||
keyword_typename
|
||||
};
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns The string associated of the keyword.
|
||||
const char* to_string(cpp_template_keyword kw) noexcept;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ template type parameter.
|
||||
class cpp_template_type_parameter final : public cpp_template_parameter
|
||||
/// \returns The keyword used in the template parameter.
|
||||
cpp_template_keyword keyword() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return keyword_;
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered template type parameter.
|
||||
/// \notes The `default_type` may be `nullptr` in which case the parameter has no default.
|
||||
static std::unique_ptr<cpp_template_type_parameter> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name,
|
||||
cpp_template_keyword kw, bool variadic,
|
||||
std::unique_ptr<cpp_type> default_type = nullptr);
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the default type.
|
||||
type_safe::optional_ref<const cpp_type> default_type() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(default_type_.get());
|
||||
}
|
||||
|
||||
/// \returns The keyword used in the template parameter.
|
||||
cpp_template_keyword keyword() const noexcept
|
||||
{
|
||||
return keyword_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_type_parameter(std::string name, cpp_template_keyword kw, bool variadic,
|
||||
std::unique_ptr<cpp_type> default_type)
|
||||
: cpp_template_parameter(std::move(name), variadic),
|
||||
default_type_(std::move(default_type)),
|
||||
keyword_(kw)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_type> default_type_;
|
||||
cpp_template_keyword keyword_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// \returns A [ts::optional]() that is the default template.
|
||||
type_safe::optional<cpp_template_ref> default_template() const noexcept
|
||||
{
|
||||
struct cpp_template_parameter_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
return default_;
|
||||
}
|
||||
|
||||
/// Reference to a [cppast::cpp_template_type_parameter]().
|
||||
using cpp_template_type_parameter_ref =
|
||||
basic_cpp_entity_ref<cpp_template_type_parameter,
|
||||
detail::cpp_template_parameter_ref_predicate>;
|
||||
private:
|
||||
cpp_template_template_parameter(std::string name, bool variadic)
|
||||
: cpp_template_parameter(std::move(name), variadic),
|
||||
keyword_(cpp_template_keyword::keyword_class)
|
||||
{}
|
||||
|
||||
/// A [cppast::cpp_type]() defined by a [cppast::cpp_template_type_parameter]().
|
||||
class cpp_template_parameter_type final : public cpp_type
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
detail::intrusive_list<cpp_template_parameter> parameters_;
|
||||
type_safe::optional<cpp_template_ref> default_;
|
||||
cpp_template_keyword keyword_;
|
||||
};
|
||||
|
||||
/// An argument for a [cppast::cpp_template_parameter]().
|
||||
///
|
||||
/// It is based on a [ts::variant]() of [cppast::cpp_type]() (for
|
||||
/// [cppast::cpp_template_type_parameter]()), [cppast::cpp_expression]() (for
|
||||
/// [cppast::cpp_non_type_template_parameter]()) and [cppast::cpp_template_ref]() (for
|
||||
/// [cppast::cpp_template_template_parameter]().
|
||||
class cpp_template_argument
|
||||
{
|
||||
public:
|
||||
/// \effects Initializes it passing a type as argument.
|
||||
/// This corresponds to a [cppast::cpp_template_type_parameter]().
|
||||
/// \notes This constructor only participates in overload resolution if `T` is dervied from
|
||||
/// [cppast::cpp_type](). \param 1 \exclude
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_base_of<cpp_type, T>::value, int>::type = 0>
|
||||
cpp_template_argument(std::unique_ptr<T> type)
|
||||
: arg_(std::unique_ptr<cpp_type>(std::move(type)))
|
||||
{}
|
||||
|
||||
/// \effects Initializes it passing an expression as argument.
|
||||
/// This corresponds to a [cppast::cpp_non_type_template_parameter]().
|
||||
/// \notes This constructor only participates in overload resolution if `T` is dervied from
|
||||
/// [cppast::cpp_expression](). \param 1 \exclude
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<std::is_base_of<cpp_expression, T>::value>::type>
|
||||
cpp_template_argument(std::unique_ptr<T> expr)
|
||||
: arg_(std::unique_ptr<cpp_expression>(std::move(expr)))
|
||||
{}
|
||||
|
||||
/// \effects Initializes it passing a template as argument.
|
||||
/// This corresponds to a [cppast::cpp_template_template_parameter]().
|
||||
cpp_template_argument(cpp_template_ref templ) : arg_(std::move(templ)) {}
|
||||
|
||||
type_safe::optional_ref<const cpp_type> type() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created parameter type.
|
||||
static std::unique_ptr<cpp_template_parameter_type> build(
|
||||
cpp_template_type_parameter_ref parameter)
|
||||
{
|
||||
return std::unique_ptr<cpp_template_parameter_type>(
|
||||
new cpp_template_parameter_type(std::move(parameter)));
|
||||
}
|
||||
return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_type>>{})
|
||||
.map([](const std::unique_ptr<cpp_type>& type) { return type_safe::ref(*type); });
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_template_type_parameter]() this type refers to.
|
||||
const cpp_template_type_parameter_ref& entity() const noexcept
|
||||
{
|
||||
return parameter_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_parameter_type(cpp_template_type_parameter_ref parameter)
|
||||
: parameter_(std::move(parameter))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::template_parameter_t;
|
||||
}
|
||||
|
||||
cpp_template_type_parameter_ref parameter_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ non-type template parameter.
|
||||
class cpp_non_type_template_parameter final : public cpp_template_parameter,
|
||||
public cpp_variable_base
|
||||
type_safe::optional_ref<const cpp_expression> expression() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_expression>>{})
|
||||
.map([](const std::unique_ptr<cpp_expression>& expr) { return type_safe::ref(*expr); });
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered non type template parameter.
|
||||
/// \notes The `default_value` may be `nullptr` in which case the parameter has no default.
|
||||
static std::unique_ptr<cpp_non_type_template_parameter> build(
|
||||
const cpp_entity_index& idx, cpp_entity_id id, std::string name,
|
||||
std::unique_ptr<cpp_type> type, bool is_variadic,
|
||||
std::unique_ptr<cpp_expression> default_value = nullptr);
|
||||
|
||||
private:
|
||||
cpp_non_type_template_parameter(std::string name, std::unique_ptr<cpp_type> type,
|
||||
bool variadic, std::unique_ptr<cpp_expression> def)
|
||||
: cpp_template_parameter(std::move(name), variadic),
|
||||
cpp_variable_base(std::move(type), std::move(def))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
type_safe::optional_ref<const cpp_template_ref> template_ref() const noexcept
|
||||
{
|
||||
struct cpp_template_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
return arg_.optional_value(type_safe::variant_type<cpp_template_ref>{});
|
||||
}
|
||||
|
||||
class cpp_template;
|
||||
|
||||
/// A reference to a [cppast::cpp_template]() or a [cppast::cpp_template_template_parameter]().
|
||||
using cpp_template_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_template_ref_predicate>;
|
||||
|
||||
/// A [cppast::cpp_entity]() modelling a C++ template template parameter.
|
||||
class cpp_template_template_parameter final : public cpp_template_parameter
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builds a [cppast::cpp_template_template_parameter]().
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// \effects Sets the name and whether it is variadic.
|
||||
builder(std::string name, bool variadic)
|
||||
: parameter_(new cpp_template_template_parameter(std::move(name), variadic))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Sets the keyword,
|
||||
/// default is [cpp_template_keyword::keyword_class]().
|
||||
void keyword(cpp_template_keyword kw)
|
||||
{
|
||||
parameter_->keyword_ = kw;
|
||||
}
|
||||
|
||||
/// \effects Adds a parameter to the template.
|
||||
void add_parameter(std::unique_ptr<cpp_template_parameter> param)
|
||||
{
|
||||
parameter_->parameters_.push_back(*parameter_, std::move(param));
|
||||
}
|
||||
|
||||
/// \effects Sets the default template.
|
||||
void default_template(cpp_template_ref templ)
|
||||
{
|
||||
parameter_->default_ = std::move(templ);
|
||||
}
|
||||
|
||||
/// \effects Registers the parameter in the [cppast::cpp_entity_index](),
|
||||
/// using the given [cppast::cpp_entity_id]().
|
||||
/// \returns The finished parameter.
|
||||
std::unique_ptr<cpp_template_template_parameter> finish(const cpp_entity_index& idx,
|
||||
cpp_entity_id id)
|
||||
{
|
||||
idx.register_definition(std::move(id), type_safe::ref(*parameter_));
|
||||
return std::move(parameter_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_template_template_parameter> parameter_;
|
||||
};
|
||||
|
||||
/// \returns An iteratable object containing the template parameters of the template template parameter.
|
||||
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
|
||||
{
|
||||
return type_safe::ref(parameters_);
|
||||
}
|
||||
|
||||
/// \returns The keyword used in the template parameter.
|
||||
cpp_template_keyword keyword() const noexcept
|
||||
{
|
||||
return keyword_;
|
||||
}
|
||||
|
||||
/// \returns A [ts::optional]() that is the default template.
|
||||
type_safe::optional<cpp_template_ref> default_template() const noexcept
|
||||
{
|
||||
return default_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_template_template_parameter(std::string name, bool variadic)
|
||||
: cpp_template_parameter(std::move(name), variadic),
|
||||
keyword_(cpp_template_keyword::keyword_class)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
detail::intrusive_list<cpp_template_parameter> parameters_;
|
||||
type_safe::optional<cpp_template_ref> default_;
|
||||
cpp_template_keyword keyword_;
|
||||
};
|
||||
|
||||
/// An argument for a [cppast::cpp_template_parameter]().
|
||||
///
|
||||
/// It is based on a [ts::variant]() of [cppast::cpp_type]() (for [cppast::cpp_template_type_parameter]()),
|
||||
/// [cppast::cpp_expression]() (for [cppast::cpp_non_type_template_parameter]()) and [cppast::cpp_template_ref]()
|
||||
/// (for [cppast::cpp_template_template_parameter]().
|
||||
class cpp_template_argument
|
||||
{
|
||||
public:
|
||||
/// \effects Initializes it passing a type as argument.
|
||||
/// This corresponds to a [cppast::cpp_template_type_parameter]().
|
||||
/// \notes This constructor only participates in overload resolution if `T` is dervied from [cppast::cpp_type]().
|
||||
/// \param 1
|
||||
/// \exclude
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_base_of<cpp_type, T>::value, int>::type = 0>
|
||||
cpp_template_argument(std::unique_ptr<T> type)
|
||||
: arg_(std::unique_ptr<cpp_type>(std::move(type)))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Initializes it passing an expression as argument.
|
||||
/// This corresponds to a [cppast::cpp_non_type_template_parameter]().
|
||||
/// \notes This constructor only participates in overload resolution if `T` is dervied from [cppast::cpp_expression]().
|
||||
/// \param 1
|
||||
/// \exclude
|
||||
template <typename T, typename = typename std::enable_if<
|
||||
std::is_base_of<cpp_expression, T>::value>::type>
|
||||
cpp_template_argument(std::unique_ptr<T> expr)
|
||||
: arg_(std::unique_ptr<cpp_expression>(std::move(expr)))
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Initializes it passing a template as argument.
|
||||
/// This corresponds to a [cppast::cpp_template_template_parameter]().
|
||||
cpp_template_argument(cpp_template_ref templ) : arg_(std::move(templ)) {}
|
||||
|
||||
type_safe::optional_ref<const cpp_type> type() const noexcept
|
||||
{
|
||||
return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_type>>{})
|
||||
.map([](const std::unique_ptr<cpp_type>& type) { return type_safe::ref(*type); });
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_expression> expression() const noexcept
|
||||
{
|
||||
return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_expression>>{})
|
||||
.map([](const std::unique_ptr<cpp_expression>& expr) {
|
||||
return type_safe::ref(*expr);
|
||||
});
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_template_ref> template_ref() const noexcept
|
||||
{
|
||||
return arg_.optional_value(type_safe::variant_type<cpp_template_ref>{});
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::variant<std::unique_ptr<cpp_type>, std::unique_ptr<cpp_expression>,
|
||||
cpp_template_ref>
|
||||
arg_;
|
||||
};
|
||||
private:
|
||||
type_safe::variant<std::unique_ptr<cpp_type>, std::unique_ptr<cpp_expression>, cpp_template_ref>
|
||||
arg_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -12,126 +12,124 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// The kinds of C++ tokens.
|
||||
enum class cpp_token_kind
|
||||
/// The kinds of C++ tokens.
|
||||
enum class cpp_token_kind
|
||||
{
|
||||
identifier, //< Any identifier.
|
||||
keyword, //< Any keyword.
|
||||
int_literal, //< An integer literal.
|
||||
float_literal, //< A floating point literal.
|
||||
char_literal, //< A character literal.
|
||||
string_literal, //< A string literal.
|
||||
punctuation //< Any other punctuation.
|
||||
};
|
||||
|
||||
/// A C++ token.
|
||||
struct cpp_token
|
||||
{
|
||||
std::string spelling;
|
||||
cpp_token_kind kind;
|
||||
|
||||
cpp_token(cpp_token_kind kind, std::string spelling) : spelling(std::move(spelling)), kind(kind)
|
||||
{}
|
||||
|
||||
friend bool operator==(const cpp_token& lhs, const cpp_token& rhs) noexcept
|
||||
{
|
||||
identifier, //< Any identifier.
|
||||
keyword, //< Any keyword.
|
||||
int_literal, //< An integer literal.
|
||||
float_literal, //< A floating point literal.
|
||||
char_literal, //< A character literal.
|
||||
string_literal, //< A string literal.
|
||||
punctuation //< Any other punctuation.
|
||||
};
|
||||
return lhs.spelling == rhs.spelling;
|
||||
}
|
||||
|
||||
/// A C++ token.
|
||||
struct cpp_token
|
||||
friend bool operator!=(const cpp_token& lhs, const cpp_token& rhs) noexcept
|
||||
{
|
||||
std::string spelling;
|
||||
cpp_token_kind kind;
|
||||
return !(rhs == lhs);
|
||||
}
|
||||
};
|
||||
|
||||
cpp_token(cpp_token_kind kind, std::string spelling)
|
||||
: spelling(std::move(spelling)), kind(kind)
|
||||
{
|
||||
}
|
||||
|
||||
friend bool operator==(const cpp_token& lhs, const cpp_token& rhs) noexcept
|
||||
{
|
||||
return lhs.spelling == rhs.spelling;
|
||||
}
|
||||
|
||||
friend bool operator!=(const cpp_token& lhs, const cpp_token& rhs) noexcept
|
||||
{
|
||||
return !(rhs == lhs);
|
||||
}
|
||||
};
|
||||
|
||||
/// A combination of multiple C++ tokens.
|
||||
class cpp_token_string
|
||||
/// A combination of multiple C++ tokens.
|
||||
class cpp_token_string
|
||||
{
|
||||
public:
|
||||
/// Builds a token string.
|
||||
class builder
|
||||
{
|
||||
public:
|
||||
/// Builds a token string.
|
||||
class builder
|
||||
builder() = default;
|
||||
|
||||
/// \effects Adds a token.
|
||||
void add_token(cpp_token tok)
|
||||
{
|
||||
public:
|
||||
builder() = default;
|
||||
|
||||
/// \effects Adds a token.
|
||||
void add_token(cpp_token tok)
|
||||
{
|
||||
tokens_.push_back(std::move(tok));
|
||||
}
|
||||
|
||||
/// \effects Converts a trailing `>>` to `>` token.
|
||||
void unmunch();
|
||||
|
||||
/// \returns The finished string.
|
||||
cpp_token_string finish()
|
||||
{
|
||||
return cpp_token_string(std::move(tokens_));
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<cpp_token> tokens_;
|
||||
};
|
||||
|
||||
/// Tokenizes a string.
|
||||
/// \effects Splits the string into C++ tokens.
|
||||
/// The string must contain valid tokens and must already be preprocessed (i.e. translation phase 6 is already done).
|
||||
/// \returns The tokenized string.
|
||||
static cpp_token_string tokenize(std::string str);
|
||||
|
||||
/// \effects Creates it from a sequence of tokens.
|
||||
cpp_token_string(std::vector<cpp_token> tokens) : tokens_(std::move(tokens)) {}
|
||||
|
||||
/// \exclude target
|
||||
using iterator = std::vector<cpp_token>::const_iterator;
|
||||
|
||||
/// \returns An iterator to the first token.
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return tokens_.begin();
|
||||
tokens_.push_back(std::move(tok));
|
||||
}
|
||||
|
||||
/// \returns An iterator one past the last token.
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return tokens_.end();
|
||||
}
|
||||
/// \effects Converts a trailing `>>` to `>` token.
|
||||
void unmunch();
|
||||
|
||||
/// \returns Whether or not the string is empty.
|
||||
bool empty() const noexcept
|
||||
/// \returns The finished string.
|
||||
cpp_token_string finish()
|
||||
{
|
||||
return tokens_.empty();
|
||||
return cpp_token_string(std::move(tokens_));
|
||||
}
|
||||
|
||||
/// \returns A reference to the first token.
|
||||
const cpp_token& front() const noexcept
|
||||
{
|
||||
return tokens_.front();
|
||||
}
|
||||
|
||||
/// \returns A reference to the last token.
|
||||
const cpp_token& back() const noexcept
|
||||
{
|
||||
return tokens_.back();
|
||||
}
|
||||
|
||||
/// \returns The string representation of the tokens, without any whitespace.
|
||||
std::string as_string() const;
|
||||
|
||||
private:
|
||||
std::vector<cpp_token> tokens_;
|
||||
|
||||
friend bool operator==(const cpp_token_string& lhs, const cpp_token_string& rhs);
|
||||
};
|
||||
|
||||
bool operator==(const cpp_token_string& lhs, const cpp_token_string& rhs);
|
||||
/// Tokenizes a string.
|
||||
/// \effects Splits the string into C++ tokens.
|
||||
/// The string must contain valid tokens and must already be preprocessed (i.e. translation
|
||||
/// phase 6 is already done). \returns The tokenized string.
|
||||
static cpp_token_string tokenize(std::string str);
|
||||
|
||||
inline bool operator!=(const cpp_token_string& lhs, const cpp_token_string& rhs)
|
||||
/// \effects Creates it from a sequence of tokens.
|
||||
cpp_token_string(std::vector<cpp_token> tokens) : tokens_(std::move(tokens)) {}
|
||||
|
||||
/// \exclude target
|
||||
using iterator = std::vector<cpp_token>::const_iterator;
|
||||
|
||||
/// \returns An iterator to the first token.
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
return tokens_.begin();
|
||||
}
|
||||
|
||||
/// \returns An iterator one past the last token.
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return tokens_.end();
|
||||
}
|
||||
|
||||
/// \returns Whether or not the string is empty.
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return tokens_.empty();
|
||||
}
|
||||
|
||||
/// \returns A reference to the first token.
|
||||
const cpp_token& front() const noexcept
|
||||
{
|
||||
return tokens_.front();
|
||||
}
|
||||
|
||||
/// \returns A reference to the last token.
|
||||
const cpp_token& back() const noexcept
|
||||
{
|
||||
return tokens_.back();
|
||||
}
|
||||
|
||||
/// \returns The string representation of the tokens, without any whitespace.
|
||||
std::string as_string() const;
|
||||
|
||||
private:
|
||||
std::vector<cpp_token> tokens_;
|
||||
|
||||
friend bool operator==(const cpp_token_string& lhs, const cpp_token_string& rhs);
|
||||
};
|
||||
|
||||
bool operator==(const cpp_token_string& lhs, const cpp_token_string& rhs);
|
||||
|
||||
inline bool operator!=(const cpp_token_string& lhs, const cpp_token_string& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_TOKEN_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -8,455 +8,452 @@
|
|||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
#include <cppast/cpp_entity_ref.hpp>
|
||||
#include <cppast/code_generator.hpp>
|
||||
#include <cppast/cpp_entity_ref.hpp>
|
||||
#include <cppast/detail/intrusive_list.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
/// The kinds of a [cppast::cpp_type]().
|
||||
enum class cpp_type_kind
|
||||
/// The kinds of a [cppast::cpp_type]().
|
||||
enum class cpp_type_kind
|
||||
{
|
||||
builtin_t,
|
||||
user_defined_t,
|
||||
|
||||
auto_t,
|
||||
decltype_t,
|
||||
decltype_auto_t,
|
||||
|
||||
cv_qualified_t,
|
||||
pointer_t,
|
||||
reference_t,
|
||||
|
||||
array_t,
|
||||
function_t,
|
||||
member_function_t,
|
||||
member_object_t,
|
||||
|
||||
template_parameter_t,
|
||||
template_instantiation_t,
|
||||
|
||||
dependent_t,
|
||||
|
||||
unexposed_t,
|
||||
};
|
||||
|
||||
/// Base class for all C++ types.
|
||||
class cpp_type : detail::intrusive_list_node<cpp_type>
|
||||
{
|
||||
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
|
||||
{
|
||||
builtin_t,
|
||||
user_defined_t,
|
||||
|
||||
auto_t,
|
||||
decltype_t,
|
||||
decltype_auto_t,
|
||||
|
||||
cv_qualified_t,
|
||||
pointer_t,
|
||||
reference_t,
|
||||
|
||||
array_t,
|
||||
function_t,
|
||||
member_function_t,
|
||||
member_object_t,
|
||||
|
||||
template_parameter_t,
|
||||
template_instantiation_t,
|
||||
|
||||
dependent_t,
|
||||
|
||||
unexposed_t,
|
||||
};
|
||||
|
||||
/// Base class for all C++ types.
|
||||
class cpp_type : detail::intrusive_list_node<cpp_type>
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
protected:
|
||||
cpp_type() noexcept : user_data_(nullptr) {}
|
||||
|
||||
private:
|
||||
/// \returns The [cppast::cpp_type_kind]().
|
||||
virtual cpp_type_kind do_get_kind() const noexcept = 0;
|
||||
|
||||
void on_insert(const cpp_type&) {}
|
||||
|
||||
mutable std::atomic<void*> user_data_;
|
||||
|
||||
template <typename T>
|
||||
friend struct detail::intrusive_list_access;
|
||||
friend detail::intrusive_list_node<cpp_type>;
|
||||
};
|
||||
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_unexposed_type> build(std::string name)
|
||||
{
|
||||
return std::unique_ptr<cpp_unexposed_type>(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_t;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/// The C++ builtin types.
|
||||
enum cpp_builtin_type_kind
|
||||
{
|
||||
cpp_void, //< `void`
|
||||
|
||||
cpp_bool, //< `bool`
|
||||
|
||||
cpp_uchar, //< `unsigned char`
|
||||
cpp_ushort, //< `unsigned short`
|
||||
cpp_uint, //< `unsigned int`
|
||||
cpp_ulong, //< `unsigned long`
|
||||
cpp_ulonglong, //< `unsigned long long`
|
||||
cpp_uint128, //< `unsigned __int128`
|
||||
|
||||
cpp_schar, //< `signed char`
|
||||
cpp_short, //< `short`
|
||||
cpp_int, //< `int`
|
||||
cpp_long, //< `long`
|
||||
cpp_longlong, //< `long long`
|
||||
cpp_int128, //< `__int128`
|
||||
|
||||
cpp_float, //< `float`
|
||||
cpp_double, //< `double`
|
||||
cpp_longdouble, //< `long double`
|
||||
cpp_float128, //< `__float128`
|
||||
|
||||
cpp_char, //< `char`
|
||||
cpp_wchar, //< `wchar_t`
|
||||
cpp_char16, //< `char16_t`
|
||||
cpp_char32, //< `char32_t`
|
||||
|
||||
cpp_nullptr, //< `decltype(nullptr)` aka `std::nullptr_t`
|
||||
};
|
||||
|
||||
/// \returns The string representing the spelling of that type in the source code.
|
||||
const char* to_string(cpp_builtin_type_kind kind) noexcept;
|
||||
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_builtin_type> build(cpp_builtin_type_kind kind)
|
||||
{
|
||||
return std::unique_ptr<cpp_builtin_type>(new cpp_builtin_type(kind));
|
||||
}
|
||||
|
||||
/// \returns Which builtin type it is.
|
||||
cpp_builtin_type_kind builtin_type_kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_builtin_type(cpp_builtin_type_kind kind) : kind_(kind) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::builtin_t;
|
||||
}
|
||||
|
||||
cpp_builtin_type_kind kind_;
|
||||
};
|
||||
|
||||
/// \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<cpp_entity, detail::cpp_type_ref_predicate>;
|
||||
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_user_defined_type> build(cpp_type_ref entity)
|
||||
{
|
||||
return std::unique_ptr<cpp_user_defined_type>(
|
||||
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_t;
|
||||
}
|
||||
|
||||
cpp_type_ref entity_;
|
||||
};
|
||||
|
||||
/// A [cppast::cpp_type]() that isn't given but deduced by `auto`.
|
||||
class cpp_auto_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `auto` type.
|
||||
static std::unique_ptr<cpp_auto_type> build()
|
||||
{
|
||||
return std::unique_ptr<cpp_auto_type>(new cpp_auto_type);
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_auto_type() = default;
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::auto_t;
|
||||
}
|
||||
};
|
||||
|
||||
class cpp_template_parameter_type;
|
||||
class cpp_template_instantiation_type;
|
||||
|
||||
/// A [cppast::cpp_type]() that depends on another type.
|
||||
class cpp_dependent_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created type dependent on a [cppast::cpp_template_parameter_type]().
|
||||
static std::unique_ptr<cpp_dependent_type> build(
|
||||
std::string name, std::unique_ptr<cpp_template_parameter_type> dependee);
|
||||
|
||||
/// \returns A newly created type dependent on a [cppast::cpp_template_instantiation_type]().
|
||||
static std::unique_ptr<cpp_dependent_type> build(
|
||||
std::string name, std::unique_ptr<cpp_template_instantiation_type> dependee);
|
||||
|
||||
/// \returns The name of the dependent type.
|
||||
/// \notes It does not include a scope.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_type]() it depends one.
|
||||
/// \notes This is either [cppast::cpp_template_parameter_type]() or [cppast:cpp_template_instantiation_type]().
|
||||
const cpp_type& dependee() const noexcept
|
||||
{
|
||||
return *dependee_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_dependent_type(std::string name, std::unique_ptr<cpp_type> dependee)
|
||||
: name_(std::move(name)), dependee_(std::move(dependee))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::dependent_t;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
std::unique_ptr<cpp_type> dependee_;
|
||||
};
|
||||
|
||||
/// 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;
|
||||
return do_get_kind();
|
||||
}
|
||||
|
||||
/// \returns `true` if the qualifier contains `volatile`.
|
||||
inline bool is_volatile(cpp_cv cv) noexcept
|
||||
/// \returns The specified user data.
|
||||
void* user_data() const noexcept
|
||||
{
|
||||
return cv == cpp_cv_volatile || cv == cpp_cv_const_volatile;
|
||||
return user_data_.load();
|
||||
}
|
||||
|
||||
/// A [cppast::cpp_cv]() qualified [cppast::cpp_type]().
|
||||
class cpp_cv_qualified_type final : public cpp_type
|
||||
/// \effects Sets some kind of user data.
|
||||
///
|
||||
/// User data is just some kind of pointer, there are no requirements.
|
||||
/// The class will do no lifetime management.
|
||||
///
|
||||
/// User data is useful if you need to store additional data for an entity without the need to
|
||||
/// maintain a registry.
|
||||
void set_user_data(void* data) const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created qualified type.
|
||||
/// \requires `cv` must not be [cppast::cpp_cv::cpp_cv_none]().
|
||||
static std::unique_ptr<cpp_cv_qualified_type> build(std::unique_ptr<cpp_type> type,
|
||||
cpp_cv cv)
|
||||
{
|
||||
DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{});
|
||||
return std::unique_ptr<cpp_cv_qualified_type>(
|
||||
new cpp_cv_qualified_type(std::move(type), cv));
|
||||
}
|
||||
user_data_ = data;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_type]() that is qualified.
|
||||
const cpp_type& type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
protected:
|
||||
cpp_type() noexcept : user_data_(nullptr) {}
|
||||
|
||||
/// \returns The [cppast::cpp_cv]() qualifier.
|
||||
cpp_cv cv_qualifier() const noexcept
|
||||
{
|
||||
return cv_;
|
||||
}
|
||||
private:
|
||||
/// \returns The [cppast::cpp_type_kind]().
|
||||
virtual cpp_type_kind do_get_kind() const noexcept = 0;
|
||||
|
||||
private:
|
||||
cpp_cv_qualified_type(std::unique_ptr<cpp_type> type, cpp_cv cv)
|
||||
: type_(std::move(type)), cv_(cv)
|
||||
{
|
||||
}
|
||||
void on_insert(const cpp_type&) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::cv_qualified_t;
|
||||
}
|
||||
mutable std::atomic<void*> user_data_;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
cpp_cv cv_;
|
||||
template <typename T>
|
||||
friend struct detail::intrusive_list_access;
|
||||
friend detail::intrusive_list_node<cpp_type>;
|
||||
};
|
||||
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_unexposed_type> build(std::string name)
|
||||
{
|
||||
return std::unique_ptr<cpp_unexposed_type>(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_t;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/// The C++ builtin types.
|
||||
enum cpp_builtin_type_kind
|
||||
{
|
||||
cpp_void, //< `void`
|
||||
|
||||
cpp_bool, //< `bool`
|
||||
|
||||
cpp_uchar, //< `unsigned char`
|
||||
cpp_ushort, //< `unsigned short`
|
||||
cpp_uint, //< `unsigned int`
|
||||
cpp_ulong, //< `unsigned long`
|
||||
cpp_ulonglong, //< `unsigned long long`
|
||||
cpp_uint128, //< `unsigned __int128`
|
||||
|
||||
cpp_schar, //< `signed char`
|
||||
cpp_short, //< `short`
|
||||
cpp_int, //< `int`
|
||||
cpp_long, //< `long`
|
||||
cpp_longlong, //< `long long`
|
||||
cpp_int128, //< `__int128`
|
||||
|
||||
cpp_float, //< `float`
|
||||
cpp_double, //< `double`
|
||||
cpp_longdouble, //< `long double`
|
||||
cpp_float128, //< `__float128`
|
||||
|
||||
cpp_char, //< `char`
|
||||
cpp_wchar, //< `wchar_t`
|
||||
cpp_char16, //< `char16_t`
|
||||
cpp_char32, //< `char32_t`
|
||||
|
||||
cpp_nullptr, //< `decltype(nullptr)` aka `std::nullptr_t`
|
||||
};
|
||||
|
||||
/// \returns The string representing the spelling of that type in the source code.
|
||||
const char* to_string(cpp_builtin_type_kind kind) noexcept;
|
||||
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_builtin_type> build(cpp_builtin_type_kind kind)
|
||||
{
|
||||
return std::unique_ptr<cpp_builtin_type>(new cpp_builtin_type(kind));
|
||||
}
|
||||
|
||||
/// \returns Which builtin type it is.
|
||||
cpp_builtin_type_kind builtin_type_kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_builtin_type(cpp_builtin_type_kind kind) : kind_(kind) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::builtin_t;
|
||||
}
|
||||
|
||||
cpp_builtin_type_kind kind_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
struct cpp_type_ref_predicate
|
||||
{
|
||||
bool operator()(const cpp_entity& e);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// \returns The type without top-level const/volatile qualifiers.
|
||||
const cpp_type& remove_cv(const cpp_type& type) noexcept;
|
||||
/// Reference to a [cppast::cpp_entity]() representing a new type.
|
||||
using cpp_type_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_type_ref_predicate>;
|
||||
|
||||
/// \returns The type without top-level const qualifiers.
|
||||
const cpp_type& remove_const(const cpp_type& type) noexcept;
|
||||
|
||||
/// \returns The type without top-level volatile qualifiers.
|
||||
const cpp_type& remove_volatile(const cpp_type& type) noexcept;
|
||||
|
||||
/// A pointer to a [cppast::cpp_type]().
|
||||
class cpp_pointer_type final : public cpp_type
|
||||
/// 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.
|
||||
static std::unique_ptr<cpp_user_defined_type> build(cpp_type_ref entity)
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created pointer type.
|
||||
static std::unique_ptr<cpp_pointer_type> build(std::unique_ptr<cpp_type> pointee)
|
||||
{
|
||||
return std::unique_ptr<cpp_pointer_type>(new cpp_pointer_type(std::move(pointee)));
|
||||
}
|
||||
return std::unique_ptr<cpp_user_defined_type>(new cpp_user_defined_type(std::move(entity)));
|
||||
}
|
||||
|
||||
/// \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<cpp_type> pointee) : pointee_(std::move(pointee)) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::pointer_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> pointee_;
|
||||
};
|
||||
|
||||
/// The kinds of C++ references.
|
||||
enum cpp_reference
|
||||
/// \returns A [cppast::cpp_type_ref]() to the associated [cppast::cpp_entity]() that is the
|
||||
/// type.
|
||||
const cpp_type_ref& entity() const noexcept
|
||||
{
|
||||
cpp_ref_none,
|
||||
cpp_ref_lvalue,
|
||||
cpp_ref_rvalue,
|
||||
};
|
||||
return entity_;
|
||||
}
|
||||
|
||||
/// A reference to a [cppast::cpp_type]().
|
||||
class cpp_reference_type final : public cpp_type
|
||||
private:
|
||||
cpp_user_defined_type(cpp_type_ref entity) : entity_(std::move(entity)) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created qualified type.
|
||||
/// \requires `ref` must not be [cppast::cpp_reference::cpp_ref_none]().
|
||||
static std::unique_ptr<cpp_reference_type> build(std::unique_ptr<cpp_type> type,
|
||||
cpp_reference ref)
|
||||
{
|
||||
DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{});
|
||||
return std::unique_ptr<cpp_reference_type>(
|
||||
new cpp_reference_type(std::move(type), ref));
|
||||
}
|
||||
return cpp_type_kind::user_defined_t;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_type]() that is referenced.
|
||||
const cpp_type& referee() const noexcept
|
||||
{
|
||||
return *referee_;
|
||||
}
|
||||
cpp_type_ref entity_;
|
||||
};
|
||||
|
||||
/// \returns The [cppast::cpp_reference]() type.
|
||||
cpp_reference reference_kind() const noexcept
|
||||
{
|
||||
return ref_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_reference_type(std::unique_ptr<cpp_type> referee, cpp_reference ref)
|
||||
: referee_(std::move(referee)), ref_(ref)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::reference_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> referee_;
|
||||
cpp_reference ref_;
|
||||
};
|
||||
|
||||
/// \returns The type as a string representation.
|
||||
std::string to_string(const cpp_type& type);
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// A [cppast::cpp_type]() that isn't given but deduced by `auto`.
|
||||
class cpp_auto_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created `auto` type.
|
||||
static std::unique_ptr<cpp_auto_type> build()
|
||||
{
|
||||
// whether or not it requires special treatment when printing it
|
||||
// i.e. function pointer types are complex as the identifier has to be put inside
|
||||
bool is_complex_type(const cpp_type& type) noexcept;
|
||||
return std::unique_ptr<cpp_auto_type>(new cpp_auto_type);
|
||||
}
|
||||
|
||||
// write part of the type that comes before the variable name
|
||||
void write_type_prefix(code_generator::output& output, const cpp_type& type);
|
||||
private:
|
||||
cpp_auto_type() = default;
|
||||
|
||||
// write part of the type that comes after the name
|
||||
// for non-complex types, this does nothing
|
||||
void write_type_suffix(code_generator::output& output, const cpp_type& type);
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::auto_t;
|
||||
}
|
||||
};
|
||||
|
||||
// write prefix, variadic, name, suffix
|
||||
void write_type(code_generator::output& output, const cpp_type& type, std::string name,
|
||||
bool is_variadic = false);
|
||||
} // namespace detail
|
||||
class cpp_template_parameter_type;
|
||||
class cpp_template_instantiation_type;
|
||||
|
||||
/// A [cppast::cpp_type]() that depends on another type.
|
||||
class cpp_dependent_type final : public cpp_type
|
||||
{
|
||||
public:
|
||||
/// \returns A newly created type dependent on a [cppast::cpp_template_parameter_type]().
|
||||
static std::unique_ptr<cpp_dependent_type> build(
|
||||
std::string name, std::unique_ptr<cpp_template_parameter_type> dependee);
|
||||
|
||||
/// \returns A newly created type dependent on a [cppast::cpp_template_instantiation_type]().
|
||||
static std::unique_ptr<cpp_dependent_type> build(
|
||||
std::string name, std::unique_ptr<cpp_template_instantiation_type> dependee);
|
||||
|
||||
/// \returns The name of the dependent type.
|
||||
/// \notes It does not include a scope.
|
||||
const std::string& name() const noexcept
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// \returns A reference to the [cppast::cpp_type]() it depends one.
|
||||
/// \notes This is either [cppast::cpp_template_parameter_type]() or
|
||||
/// [cppast:cpp_template_instantiation_type]().
|
||||
const cpp_type& dependee() const noexcept
|
||||
{
|
||||
return *dependee_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_dependent_type(std::string name, std::unique_ptr<cpp_type> dependee)
|
||||
: name_(std::move(name)), dependee_(std::move(dependee))
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::dependent_t;
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
std::unique_ptr<cpp_type> dependee_;
|
||||
};
|
||||
|
||||
/// 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<cpp_cv_qualified_type> build(std::unique_ptr<cpp_type> type, cpp_cv cv)
|
||||
{
|
||||
DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{});
|
||||
return std::unique_ptr<cpp_cv_qualified_type>(
|
||||
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<cpp_type> 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_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
cpp_cv cv_;
|
||||
};
|
||||
|
||||
/// \returns The type without top-level const/volatile qualifiers.
|
||||
const cpp_type& remove_cv(const cpp_type& type) noexcept;
|
||||
|
||||
/// \returns The type without top-level const qualifiers.
|
||||
const cpp_type& remove_const(const cpp_type& type) noexcept;
|
||||
|
||||
/// \returns The type without top-level volatile qualifiers.
|
||||
const cpp_type& remove_volatile(const cpp_type& type) noexcept;
|
||||
|
||||
/// 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<cpp_pointer_type> build(std::unique_ptr<cpp_type> pointee)
|
||||
{
|
||||
return std::unique_ptr<cpp_pointer_type>(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<cpp_type> pointee) : pointee_(std::move(pointee)) {}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::pointer_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> 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<cpp_reference_type> build(std::unique_ptr<cpp_type> type,
|
||||
cpp_reference ref)
|
||||
{
|
||||
DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{});
|
||||
return std::unique_ptr<cpp_reference_type>(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<cpp_type> referee, cpp_reference ref)
|
||||
: referee_(std::move(referee)), ref_(ref)
|
||||
{}
|
||||
|
||||
cpp_type_kind do_get_kind() const noexcept override
|
||||
{
|
||||
return cpp_type_kind::reference_t;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_type> referee_;
|
||||
cpp_reference ref_;
|
||||
};
|
||||
|
||||
/// \returns The type as a string representation.
|
||||
std::string to_string(const cpp_type& type);
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
// whether or not it requires special treatment when printing it
|
||||
// i.e. function pointer types are complex as the identifier has to be put inside
|
||||
bool is_complex_type(const cpp_type& type) noexcept;
|
||||
|
||||
// write part of the type that comes before the variable name
|
||||
void write_type_prefix(code_generator::output& output, const cpp_type& type);
|
||||
|
||||
// write part of the type that comes after the name
|
||||
// for non-complex types, this does nothing
|
||||
void write_type_suffix(code_generator::output& output, const cpp_type& type);
|
||||
|
||||
// write prefix, variadic, name, suffix
|
||||
void write_type(code_generator::output& output, const cpp_type& type, std::string name,
|
||||
bool is_variadic = false);
|
||||
} // namespace detail
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_TYPE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,39 +10,36 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a type alias/typedef.
|
||||
/// \notes There is no distinction between `using` and `typedef` type aliases made in the AST.
|
||||
class cpp_type_alias final : public cpp_entity
|
||||
/// A [cppast::cpp_entity]() modelling a type alias/typedef.
|
||||
/// \notes There is no distinction between `using` and `typedef` type aliases made in the AST.
|
||||
class cpp_type_alias final : public cpp_entity
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered type alias.
|
||||
static std::unique_ptr<cpp_type_alias> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, std::unique_ptr<cpp_type> type);
|
||||
|
||||
/// \returns A newly created type alias that isn't registered.
|
||||
/// \notes This function is intendend for templated type aliases.
|
||||
static std::unique_ptr<cpp_type_alias> build(std::string name, std::unique_ptr<cpp_type> type);
|
||||
|
||||
/// \returns A reference to the aliased [cppast::cpp_type]().
|
||||
const cpp_type& underlying_type() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered type alias.
|
||||
static std::unique_ptr<cpp_type_alias> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name,
|
||||
std::unique_ptr<cpp_type> type);
|
||||
private:
|
||||
cpp_type_alias(std::string name, std::unique_ptr<cpp_type> type)
|
||||
: cpp_entity(std::move(name)), type_(std::move(type))
|
||||
{}
|
||||
|
||||
/// \returns A newly created type alias that isn't registered.
|
||||
/// \notes This function is intendend for templated type aliases.
|
||||
static std::unique_ptr<cpp_type_alias> build(std::string name,
|
||||
std::unique_ptr<cpp_type> type);
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
/// \returns A reference to the aliased [cppast::cpp_type]().
|
||||
const cpp_type& underlying_type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_type_alias(std::string name, std::unique_ptr<cpp_type> type)
|
||||
: cpp_entity(std::move(name)), type_(std::move(type))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
};
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_TYPE_ALIAS_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -12,61 +12,58 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a C++ variable.
|
||||
/// \notes This is not a member variable,
|
||||
/// use [cppast::cpp_member_variable]() for that.
|
||||
/// But it can be `static` member variable.
|
||||
class cpp_variable final : public cpp_entity,
|
||||
public cpp_variable_base,
|
||||
public cpp_forward_declarable
|
||||
/// A [cppast::cpp_entity]() modelling a C++ variable.
|
||||
/// \notes This is not a member variable,
|
||||
/// use [cppast::cpp_member_variable]() for that.
|
||||
/// But it can be `static` member variable.
|
||||
class cpp_variable final : public cpp_entity,
|
||||
public cpp_variable_base,
|
||||
public cpp_forward_declarable
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// \returns A newly created and registered variable.
|
||||
/// \notes The default value may be `nullptr` indicating no default value.
|
||||
static std::unique_ptr<cpp_variable> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def,
|
||||
cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr);
|
||||
|
||||
/// \returns A newly created variable that is a declaration.
|
||||
/// A declaration will not be registered and it does not have the default value.
|
||||
static std::unique_ptr<cpp_variable> build_declaration(cpp_entity_id definition_id,
|
||||
std::string name,
|
||||
std::unique_ptr<cpp_type> type,
|
||||
cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr);
|
||||
|
||||
/// \returns The [cppast::cpp_storage_specifiers]() on that variable.
|
||||
cpp_storage_class_specifiers storage_class() const noexcept
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
return storage_;
|
||||
}
|
||||
|
||||
/// \returns A newly created and registered variable.
|
||||
/// \notes The default value may be `nullptr` indicating no default value.
|
||||
static std::unique_ptr<cpp_variable> build(const cpp_entity_index& idx, cpp_entity_id id,
|
||||
std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def,
|
||||
cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr);
|
||||
/// \returns Whether the variable is marked `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return is_constexpr_;
|
||||
}
|
||||
|
||||
/// \returns A newly created variable that is a declaration.
|
||||
/// A declaration will not be registered and it does not have the default value.
|
||||
static std::unique_ptr<cpp_variable> build_declaration(cpp_entity_id definition_id,
|
||||
std::string name,
|
||||
std::unique_ptr<cpp_type> type,
|
||||
cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr);
|
||||
private:
|
||||
cpp_variable(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def, cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr)
|
||||
: cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def)),
|
||||
storage_(spec), is_constexpr_(is_constexpr)
|
||||
{}
|
||||
|
||||
/// \returns The [cppast::cpp_storage_specifiers]() on that variable.
|
||||
cpp_storage_class_specifiers storage_class() const noexcept
|
||||
{
|
||||
return storage_;
|
||||
}
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
/// \returns Whether the variable is marked `constexpr`.
|
||||
bool is_constexpr() const noexcept
|
||||
{
|
||||
return is_constexpr_;
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_variable(std::string name, std::unique_ptr<cpp_type> type,
|
||||
std::unique_ptr<cpp_expression> def, cpp_storage_class_specifiers spec,
|
||||
bool is_constexpr)
|
||||
: cpp_entity(std::move(name)),
|
||||
cpp_variable_base(std::move(type), std::move(def)),
|
||||
storage_(spec),
|
||||
is_constexpr_(is_constexpr)
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
cpp_storage_class_specifiers storage_;
|
||||
bool is_constexpr_;
|
||||
};
|
||||
cpp_storage_class_specifiers storage_;
|
||||
bool is_constexpr_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_VARIABLE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,37 +10,36 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Additional base class for all [cppast::cpp_entity]() modelling some kind of variable.
|
||||
///
|
||||
/// Examples are [cppast::cpp_variable]() or [cppast::cpp_function_parameter](),
|
||||
/// or anything that is name/type/default-value triple.
|
||||
class cpp_variable_base
|
||||
/// Additional base class for all [cppast::cpp_entity]() modelling some kind of variable.
|
||||
///
|
||||
/// Examples are [cppast::cpp_variable]() or [cppast::cpp_function_parameter](),
|
||||
/// or anything that is name/type/default-value triple.
|
||||
class cpp_variable_base
|
||||
{
|
||||
public:
|
||||
/// \returns A reference to the [cppast::cpp_type]() of the variable.
|
||||
const cpp_type& type() const noexcept
|
||||
{
|
||||
public:
|
||||
/// \returns A reference to the [cppast::cpp_type]() of the variable.
|
||||
const cpp_type& type() const noexcept
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
return *type_;
|
||||
}
|
||||
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the default value.
|
||||
type_safe::optional_ref<const cpp_expression> default_value() const noexcept
|
||||
{
|
||||
return type_safe::opt_ref(default_.get());
|
||||
}
|
||||
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the default value.
|
||||
type_safe::optional_ref<const cpp_expression> default_value() const noexcept
|
||||
{
|
||||
return type_safe::opt_ref(default_.get());
|
||||
}
|
||||
|
||||
protected:
|
||||
cpp_variable_base(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def)
|
||||
: type_(std::move(type)), default_(std::move(def))
|
||||
{
|
||||
}
|
||||
protected:
|
||||
cpp_variable_base(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def)
|
||||
: type_(std::move(type)), default_(std::move(def))
|
||||
{}
|
||||
|
||||
~cpp_variable_base() noexcept = default;
|
||||
~cpp_variable_base() noexcept = default;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
std::unique_ptr<cpp_expression> default_;
|
||||
};
|
||||
private:
|
||||
std::unique_ptr<cpp_type> type_;
|
||||
std::unique_ptr<cpp_expression> default_;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_VARIABLE_BASE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,35 +10,34 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// A [cppast::cpp_entity]() modelling a C++ alias template.
|
||||
class cpp_variable_template final : public cpp_template
|
||||
/// A [cppast::cpp_entity]() modelling a C++ alias template.
|
||||
class cpp_variable_template final : public cpp_template
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_variable_template]().
|
||||
class builder : public basic_builder<cpp_variable_template, cpp_variable>
|
||||
{
|
||||
public:
|
||||
static cpp_entity_kind kind() noexcept;
|
||||
|
||||
/// Builder for [cppast::cpp_variable_template]().
|
||||
class builder : public basic_builder<cpp_variable_template, cpp_variable>
|
||||
{
|
||||
public:
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// \returns A reference to the type variable that is being templated.
|
||||
const cpp_variable& variable() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_variable&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_variable_template(std::unique_ptr<cpp_variable> variable)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(variable.release()))
|
||||
{
|
||||
}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_variable_template, cpp_variable>;
|
||||
using basic_builder::basic_builder;
|
||||
};
|
||||
|
||||
/// \returns A reference to the type variable that is being templated.
|
||||
const cpp_variable& variable() const noexcept
|
||||
{
|
||||
return static_cast<const cpp_variable&>(*begin());
|
||||
}
|
||||
|
||||
private:
|
||||
cpp_variable_template(std::unique_ptr<cpp_variable> variable)
|
||||
: cpp_template(std::unique_ptr<cpp_entity>(variable.release()))
|
||||
{}
|
||||
|
||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||
|
||||
friend basic_builder<cpp_variable_template, cpp_variable>;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_VARIABLE_TEMPLATE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -8,31 +8,29 @@
|
|||
#include <debug_assert.hpp>
|
||||
|
||||
#ifdef CPPAST_ENABLE_ASSERTIONS
|
||||
#define CPPAST_ASSERTION_LEVEL 1
|
||||
# define CPPAST_ASSERTION_LEVEL 1
|
||||
#else
|
||||
#define CPPAST_ASSERTION_LEVEL 0
|
||||
# define CPPAST_ASSERTION_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifdef CPPAST_ENABLE_PRECONDITION_CHECKS
|
||||
#define CPPAST_PRECONDITION_LEVEL 1
|
||||
# define CPPAST_PRECONDITION_LEVEL 1
|
||||
#else
|
||||
#define CPPAST_PRECONDITION_LEVEL 0
|
||||
# define CPPAST_PRECONDITION_LEVEL 0
|
||||
#endif
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct assert_handler : debug_assert::set_level<CPPAST_ASSERTION_LEVEL>,
|
||||
debug_assert::default_handler
|
||||
{
|
||||
};
|
||||
namespace detail
|
||||
{
|
||||
struct assert_handler : debug_assert::set_level<CPPAST_ASSERTION_LEVEL>,
|
||||
debug_assert::default_handler
|
||||
{};
|
||||
|
||||
struct precondition_error_handler : debug_assert::set_level<CPPAST_PRECONDITION_LEVEL>,
|
||||
debug_assert::default_handler
|
||||
{
|
||||
};
|
||||
}
|
||||
} // namespace cppast::detail
|
||||
struct precondition_error_handler : debug_assert::set_level<CPPAST_PRECONDITION_LEVEL>,
|
||||
debug_assert::default_handler
|
||||
{};
|
||||
} // namespace detail
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_ASSERT_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#ifndef CPPAST_INTRUSIVE_LIST_HPP_INCLUDED
|
||||
#define CPPAST_INTRUSIVE_LIST_HPP_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include <type_safe/optional_ref.hpp>
|
||||
|
||||
|
|
@ -14,228 +14,226 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_file;
|
||||
class cpp_file;
|
||||
|
||||
namespace detail
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
class intrusive_list_node
|
||||
{
|
||||
template <typename T>
|
||||
class intrusive_list_node
|
||||
std::unique_ptr<T> next_;
|
||||
|
||||
void do_on_insert(const T& parent) noexcept
|
||||
{
|
||||
std::unique_ptr<T> next_;
|
||||
static_cast<T&>(*this).on_insert(parent);
|
||||
}
|
||||
|
||||
void do_on_insert(const T& parent) noexcept
|
||||
{
|
||||
static_cast<T&>(*this).on_insert(parent);
|
||||
}
|
||||
template <typename U>
|
||||
friend struct intrusive_list_access;
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
friend struct intrusive_list_access;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct intrusive_list_access
|
||||
template <typename T>
|
||||
struct intrusive_list_access
|
||||
{
|
||||
template <typename U>
|
||||
static T* get_next(const U& obj)
|
||||
{
|
||||
template <typename U>
|
||||
static T* get_next(const U& obj)
|
||||
{
|
||||
static_assert(std::is_base_of<U, T>::value, "must be a base");
|
||||
return static_cast<T*>(obj.next_.get());
|
||||
}
|
||||
static_assert(std::is_base_of<U, T>::value, "must be a base");
|
||||
return static_cast<T*>(obj.next_.get());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
static T* set_next(U& obj, std::unique_ptr<T> node)
|
||||
{
|
||||
static_assert(std::is_base_of<U, T>::value, "must be a base");
|
||||
obj.next_ = std::move(node);
|
||||
return static_cast<T*>(obj.next_.get());
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
static void on_insert(U& obj, const V& parent)
|
||||
{
|
||||
obj.do_on_insert(parent);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class intrusive_list_iterator
|
||||
template <typename U>
|
||||
static T* set_next(U& obj, std::unique_ptr<T> node)
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using pointer = T*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
static_assert(std::is_base_of<U, T>::value, "must be a base");
|
||||
obj.next_ = std::move(node);
|
||||
return static_cast<T*>(obj.next_.get());
|
||||
}
|
||||
|
||||
intrusive_list_iterator() noexcept : cur_(nullptr) {}
|
||||
|
||||
reference operator*() const noexcept
|
||||
{
|
||||
return *cur_;
|
||||
}
|
||||
|
||||
pointer operator->() const noexcept
|
||||
{
|
||||
return cur_;
|
||||
}
|
||||
|
||||
intrusive_list_iterator& operator++() noexcept
|
||||
{
|
||||
cur_ = intrusive_list_access<T>::get_next(*cur_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
intrusive_list_iterator operator++(int)noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const intrusive_list_iterator& a,
|
||||
const intrusive_list_iterator& b) noexcept
|
||||
{
|
||||
return a.cur_ == b.cur_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const intrusive_list_iterator& a,
|
||||
const intrusive_list_iterator& b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
intrusive_list_iterator(T* ptr) : cur_(ptr) {}
|
||||
|
||||
T* cur_;
|
||||
|
||||
template <typename U>
|
||||
friend class intrusive_list;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class intrusive_list
|
||||
template <typename U, typename V>
|
||||
static void on_insert(U& obj, const V& parent)
|
||||
{
|
||||
public:
|
||||
intrusive_list() = default;
|
||||
obj.do_on_insert(parent);
|
||||
}
|
||||
};
|
||||
|
||||
//=== modifiers ===//
|
||||
template <typename Dummy = T, typename = typename std::enable_if<
|
||||
std::is_same<Dummy, cpp_file>::value>::type>
|
||||
void push_back(std::unique_ptr<T> obj) noexcept
|
||||
{
|
||||
push_back_impl(std::move(obj));
|
||||
}
|
||||
template <typename T>
|
||||
class intrusive_list_iterator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using pointer = T*;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
template <typename U, typename = typename std::enable_if<
|
||||
!std::is_same<T, cpp_file>::value, U>::type>
|
||||
void push_back(const U& parent, std::unique_ptr<T> obj) noexcept
|
||||
{
|
||||
push_back_impl(std::move(obj));
|
||||
intrusive_list_access<T>::on_insert(last_.value(), parent);
|
||||
}
|
||||
intrusive_list_iterator() noexcept : cur_(nullptr) {}
|
||||
|
||||
//=== accesors ===//
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return first_ == nullptr;
|
||||
}
|
||||
|
||||
type_safe::optional_ref<T> front() noexcept
|
||||
{
|
||||
return type_safe::opt_ref(first_.get());
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const T> front() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(first_.get());
|
||||
}
|
||||
|
||||
type_safe::optional_ref<T> back() noexcept
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const T> back() const noexcept
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
//=== iterators ===//
|
||||
using iterator = intrusive_list_iterator<T>;
|
||||
using const_iterator = intrusive_list_iterator<const T>;
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return iterator(first_.get());
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return const_iterator(first_.get());
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
void push_back_impl(std::unique_ptr<T> obj)
|
||||
{
|
||||
DEBUG_ASSERT(obj != nullptr, detail::assert_handler{});
|
||||
|
||||
if (last_)
|
||||
{
|
||||
auto ptr = intrusive_list_access<T>::set_next(last_.value(), std::move(obj));
|
||||
last_ = type_safe::ref(*ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
first_ = std::move(obj);
|
||||
last_ = type_safe::opt_ref(first_.get());
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<T> first_;
|
||||
type_safe::optional_ref<T> last_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class iteratable_intrusive_list
|
||||
reference operator*() const noexcept
|
||||
{
|
||||
public:
|
||||
iteratable_intrusive_list(type_safe::object_ref<const intrusive_list<T>> list)
|
||||
: list_(list)
|
||||
return *cur_;
|
||||
}
|
||||
|
||||
pointer operator->() const noexcept
|
||||
{
|
||||
return cur_;
|
||||
}
|
||||
|
||||
intrusive_list_iterator& operator++() noexcept
|
||||
{
|
||||
cur_ = intrusive_list_access<T>::get_next(*cur_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
intrusive_list_iterator operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const intrusive_list_iterator& a,
|
||||
const intrusive_list_iterator& b) noexcept
|
||||
{
|
||||
return a.cur_ == b.cur_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const intrusive_list_iterator& a,
|
||||
const intrusive_list_iterator& b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
intrusive_list_iterator(T* ptr) : cur_(ptr) {}
|
||||
|
||||
T* cur_;
|
||||
|
||||
template <typename U>
|
||||
friend class intrusive_list;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class intrusive_list
|
||||
{
|
||||
public:
|
||||
intrusive_list() = default;
|
||||
|
||||
//=== modifiers ===//
|
||||
template <typename Dummy = T,
|
||||
typename = typename std::enable_if<std::is_same<Dummy, cpp_file>::value>::type>
|
||||
void push_back(std::unique_ptr<T> obj) noexcept
|
||||
{
|
||||
push_back_impl(std::move(obj));
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
typename = typename std::enable_if<!std::is_same<T, cpp_file>::value, U>::type>
|
||||
void push_back(const U& parent, std::unique_ptr<T> obj) noexcept
|
||||
{
|
||||
push_back_impl(std::move(obj));
|
||||
intrusive_list_access<T>::on_insert(last_.value(), parent);
|
||||
}
|
||||
|
||||
//=== accesors ===//
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return first_ == nullptr;
|
||||
}
|
||||
|
||||
type_safe::optional_ref<T> front() noexcept
|
||||
{
|
||||
return type_safe::opt_ref(first_.get());
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const T> front() const noexcept
|
||||
{
|
||||
return type_safe::opt_cref(first_.get());
|
||||
}
|
||||
|
||||
type_safe::optional_ref<T> back() noexcept
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const T> back() const noexcept
|
||||
{
|
||||
return last_;
|
||||
}
|
||||
|
||||
//=== iterators ===//
|
||||
using iterator = intrusive_list_iterator<T>;
|
||||
using const_iterator = intrusive_list_iterator<const T>;
|
||||
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return iterator(first_.get());
|
||||
}
|
||||
|
||||
iterator end() noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return const_iterator(first_.get());
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
void push_back_impl(std::unique_ptr<T> obj)
|
||||
{
|
||||
DEBUG_ASSERT(obj != nullptr, detail::assert_handler{});
|
||||
|
||||
if (last_)
|
||||
{
|
||||
auto ptr = intrusive_list_access<T>::set_next(last_.value(), std::move(obj));
|
||||
last_ = type_safe::ref(*ptr);
|
||||
}
|
||||
|
||||
bool empty() const noexcept
|
||||
else
|
||||
{
|
||||
return list_->empty();
|
||||
first_ = std::move(obj);
|
||||
last_ = type_safe::opt_ref(first_.get());
|
||||
}
|
||||
}
|
||||
|
||||
using iterator = typename intrusive_list<T>::const_iterator;
|
||||
std::unique_ptr<T> first_;
|
||||
type_safe::optional_ref<T> last_;
|
||||
};
|
||||
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return list_->begin();
|
||||
}
|
||||
template <typename T>
|
||||
class iteratable_intrusive_list
|
||||
{
|
||||
public:
|
||||
iteratable_intrusive_list(type_safe::object_ref<const intrusive_list<T>> list) : list_(list)
|
||||
{}
|
||||
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return list_->end();
|
||||
}
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return list_->empty();
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::object_ref<const intrusive_list<T>> list_;
|
||||
};
|
||||
}
|
||||
} // namespace cppast::detail
|
||||
using iterator = typename intrusive_list<T>::const_iterator;
|
||||
|
||||
iterator begin() const noexcept
|
||||
{
|
||||
return list_->begin();
|
||||
}
|
||||
|
||||
iterator end() const noexcept
|
||||
{
|
||||
return list_->end();
|
||||
}
|
||||
|
||||
private:
|
||||
type_safe::object_ref<const intrusive_list<T>> list_;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_INTRUSIVE_LIST_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -12,137 +12,138 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Describes a physical source location attached to a [cppast::diagnostic]().
|
||||
/// \notes All information might be unavailable.
|
||||
struct source_location
|
||||
/// Describes a physical source location attached to a [cppast::diagnostic]().
|
||||
/// \notes All information might be unavailable.
|
||||
struct source_location
|
||||
{
|
||||
type_safe::optional<std::string> entity;
|
||||
type_safe::optional<std::string> file;
|
||||
type_safe::optional<unsigned> line, column;
|
||||
|
||||
/// \returns A source location where all information is available.
|
||||
static source_location make(std::string entity, std::string file, unsigned line,
|
||||
unsigned column)
|
||||
{
|
||||
type_safe::optional<std::string> entity;
|
||||
type_safe::optional<std::string> file;
|
||||
type_safe::optional<unsigned> line, column;
|
||||
return {std::move(entity), std::move(file), line, column};
|
||||
}
|
||||
|
||||
/// \returns A source location where all information is available.
|
||||
static source_location make(std::string entity, std::string file, unsigned line,
|
||||
unsigned column)
|
||||
{
|
||||
return {std::move(entity), std::move(file), line, column};
|
||||
}
|
||||
/// \returns A source location where only file information is available.
|
||||
static source_location make_file(std::string file,
|
||||
type_safe::optional<unsigned> line = type_safe::nullopt,
|
||||
type_safe::optional<unsigned> column = type_safe::nullopt)
|
||||
{
|
||||
return {type_safe::nullopt, std::move(file), line, column};
|
||||
}
|
||||
|
||||
/// \returns A source location where only file information is available.
|
||||
static source_location make_file(std::string file,
|
||||
type_safe::optional<unsigned> line = type_safe::nullopt,
|
||||
type_safe::optional<unsigned> column = type_safe::nullopt)
|
||||
{
|
||||
return {type_safe::nullopt, std::move(file), line, column};
|
||||
}
|
||||
/// \returns A source location where only the entity name is available.
|
||||
static source_location make_entity(std::string entity)
|
||||
{
|
||||
return {std::move(entity), type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
|
||||
/// \returns A source location where only the entity name is available.
|
||||
static source_location make_entity(std::string entity)
|
||||
{
|
||||
return {std::move(entity), type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
/// \returns A source location where no information is avilable.
|
||||
static source_location make_unknown()
|
||||
{
|
||||
return {type_safe::nullopt, type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
|
||||
/// \returns A source location where no information is avilable.
|
||||
static source_location make_unknown()
|
||||
{
|
||||
return {type_safe::nullopt, type_safe::nullopt, type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
/// \returns A source location where entity and file name is available.
|
||||
static source_location make_entity(std::string entity, std::string file)
|
||||
{
|
||||
return {std::move(entity), std::move(file), type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
|
||||
/// \returns A source location where entity and file name is available.
|
||||
static source_location make_entity(std::string entity, std::string file)
|
||||
/// \returns A possible string representation of the source location.
|
||||
/// \notes It will include a separator, but no trailing whitespace.
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string result;
|
||||
if (file)
|
||||
{
|
||||
return {std::move(entity), std::move(file), type_safe::nullopt, type_safe::nullopt};
|
||||
}
|
||||
result += file.value() + ":";
|
||||
|
||||
/// \returns A possible string representation of the source location.
|
||||
/// \notes It will include a separator, but no trailing whitespace.
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string result;
|
||||
if (file)
|
||||
if (line)
|
||||
{
|
||||
result += file.value() + ":";
|
||||
result += std::to_string(line.value());
|
||||
|
||||
if (line)
|
||||
{
|
||||
result += std::to_string(line.value());
|
||||
if (column)
|
||||
result += "," + std::to_string(column.value());
|
||||
|
||||
if (column)
|
||||
result += "," + std::to_string(column.value());
|
||||
|
||||
result += ":";
|
||||
}
|
||||
|
||||
if (entity)
|
||||
result += " (" + entity.value() + "):";
|
||||
result += ":";
|
||||
}
|
||||
else if (entity && !entity.value().empty())
|
||||
result += entity.value() + ":";
|
||||
|
||||
return result;
|
||||
if (entity)
|
||||
result += " (" + entity.value() + "):";
|
||||
}
|
||||
};
|
||||
else if (entity && !entity.value().empty())
|
||||
result += entity.value() + ":";
|
||||
|
||||
/// The severity of a [cppast::diagnostic]().
|
||||
enum class severity
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// The severity of a [cppast::diagnostic]().
|
||||
enum class severity
|
||||
{
|
||||
debug, //< A debug diagnostic that is just for debugging purposes.
|
||||
info, //< An informational message.
|
||||
warning, //< A warning that doesn't impact AST generation.
|
||||
error, //< A non-critical error that does impact AST generation but not critically.
|
||||
critical, //< A critical error where AST generation isn't possible.
|
||||
/// \notes This will usually result in an exception being thrown after the diagnostic has been
|
||||
/// displayed.
|
||||
};
|
||||
|
||||
/// \returns A human-readable string describing the severity.
|
||||
inline const char* to_string(severity s) noexcept
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
debug, //< A debug diagnostic that is just for debugging purposes.
|
||||
info, //< An informational message.
|
||||
warning, //< A warning that doesn't impact AST generation.
|
||||
error, //< A non-critical error that does impact AST generation but not critically.
|
||||
critical, //< A critical error where AST generation isn't possible.
|
||||
/// \notes This will usually result in an exception being thrown after the diagnostic has been displayed.
|
||||
};
|
||||
|
||||
/// \returns A human-readable string describing the severity.
|
||||
inline const char* to_string(severity s) noexcept
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case severity::debug:
|
||||
return "debug";
|
||||
case severity::info:
|
||||
return "info";
|
||||
case severity::warning:
|
||||
return "warning";
|
||||
case severity::error:
|
||||
return "error";
|
||||
case severity::critical:
|
||||
return "critical";
|
||||
}
|
||||
|
||||
return "programmer error";
|
||||
case severity::debug:
|
||||
return "debug";
|
||||
case severity::info:
|
||||
return "info";
|
||||
case severity::warning:
|
||||
return "warning";
|
||||
case severity::error:
|
||||
return "error";
|
||||
case severity::critical:
|
||||
return "critical";
|
||||
}
|
||||
|
||||
/// A diagnostic.
|
||||
///
|
||||
/// It represents an error message from a [cppast::parser]().
|
||||
struct diagnostic
|
||||
{
|
||||
std::string message;
|
||||
source_location location;
|
||||
cppast::severity severity;
|
||||
};
|
||||
return "programmer error";
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename... Args>
|
||||
std::string format(Args&&... args)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
int dummy[] = {(stream << std::forward<Args>(args), 0)...};
|
||||
(void)dummy;
|
||||
return stream.str();
|
||||
}
|
||||
} // namespace detail
|
||||
/// A diagnostic.
|
||||
///
|
||||
/// It represents an error message from a [cppast::parser]().
|
||||
struct diagnostic
|
||||
{
|
||||
std::string message;
|
||||
source_location location;
|
||||
cppast::severity severity;
|
||||
};
|
||||
|
||||
/// Creates a diagnostic.
|
||||
/// \returns A diagnostic with the specified severity and location.
|
||||
/// The message is created by streaming each argument in order to a [std::ostringstream]().
|
||||
namespace detail
|
||||
{
|
||||
template <typename... Args>
|
||||
diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args)
|
||||
std::string format(Args&&... args)
|
||||
{
|
||||
return {detail::format(std::forward<Args>(args)...), std::move(loc), sev};
|
||||
std::ostringstream stream;
|
||||
int dummy[] = {(stream << std::forward<Args>(args), 0)...};
|
||||
(void)dummy;
|
||||
return stream.str();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Creates a diagnostic.
|
||||
/// \returns A diagnostic with the specified severity and location.
|
||||
/// The message is created by streaming each argument in order to a [std::ostringstream]().
|
||||
template <typename... Args>
|
||||
diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args)
|
||||
{
|
||||
return {detail::format(std::forward<Args>(args)...), std::move(loc), sev};
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -11,59 +11,60 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Base class for a [cppast::diagnostic]() logger.
|
||||
///
|
||||
/// Its task is controlling how diagnostic are being displayed.
|
||||
class diagnostic_logger
|
||||
/// Base class for a [cppast::diagnostic]() logger.
|
||||
///
|
||||
/// Its task is controlling how diagnostic are being displayed.
|
||||
class diagnostic_logger
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it either as verbose or not.
|
||||
explicit diagnostic_logger(bool is_verbose = false) noexcept : verbose_(is_verbose) {}
|
||||
|
||||
diagnostic_logger(const diagnostic_logger&) = delete;
|
||||
diagnostic_logger& operator=(const diagnostic_logger&) = delete;
|
||||
virtual ~diagnostic_logger() noexcept = default;
|
||||
|
||||
/// \effects Logs the diagnostic by invoking the `do_log()` member function.
|
||||
/// \returns Whether or not the diagnostic was logged.
|
||||
/// \notes `source` points to a string literal that gives additional context to what generates
|
||||
/// the message.
|
||||
bool log(const char* source, const diagnostic& d) const;
|
||||
|
||||
/// \effects Sets whether or not the logger prints debugging diagnostics.
|
||||
void set_verbose(bool value) noexcept
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it either as verbose or not.
|
||||
explicit diagnostic_logger(bool is_verbose = false) noexcept : verbose_(is_verbose) {}
|
||||
verbose_ = value;
|
||||
}
|
||||
|
||||
diagnostic_logger(const diagnostic_logger&) = delete;
|
||||
diagnostic_logger& operator=(const diagnostic_logger&) = delete;
|
||||
virtual ~diagnostic_logger() noexcept = default;
|
||||
|
||||
/// \effects Logs the diagnostic by invoking the `do_log()` member function.
|
||||
/// \returns Whether or not the diagnostic was logged.
|
||||
/// \notes `source` points to a string literal that gives additional context to what generates the message.
|
||||
bool log(const char* source, const diagnostic& d) const;
|
||||
|
||||
/// \effects Sets whether or not the logger prints debugging diagnostics.
|
||||
void set_verbose(bool value) noexcept
|
||||
{
|
||||
verbose_ = value;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the logger prints debugging diagnostics.
|
||||
bool is_verbose() const noexcept
|
||||
{
|
||||
return verbose_;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual bool do_log(const char* source, const diagnostic& d) const = 0;
|
||||
|
||||
bool verbose_;
|
||||
};
|
||||
|
||||
/// \returns The default logger object.
|
||||
type_safe::object_ref<const diagnostic_logger> default_logger() noexcept;
|
||||
|
||||
/// \returns The default verbose logger object.
|
||||
type_safe::object_ref<const diagnostic_logger> default_verbose_logger() noexcept;
|
||||
|
||||
/// A [cppast::diagnostic_logger]() that logs to `stderr`.
|
||||
///
|
||||
/// It prints all diagnostics in an implementation-defined format.
|
||||
class stderr_diagnostic_logger final : public diagnostic_logger
|
||||
/// \returns Whether or not the logger prints debugging diagnostics.
|
||||
bool is_verbose() const noexcept
|
||||
{
|
||||
public:
|
||||
using diagnostic_logger::diagnostic_logger;
|
||||
return verbose_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool do_log(const char* source, const diagnostic& d) const override;
|
||||
};
|
||||
private:
|
||||
virtual bool do_log(const char* source, const diagnostic& d) const = 0;
|
||||
|
||||
bool verbose_;
|
||||
};
|
||||
|
||||
/// \returns The default logger object.
|
||||
type_safe::object_ref<const diagnostic_logger> default_logger() noexcept;
|
||||
|
||||
/// \returns The default verbose logger object.
|
||||
type_safe::object_ref<const diagnostic_logger> default_verbose_logger() noexcept;
|
||||
|
||||
/// A [cppast::diagnostic_logger]() that logs to `stderr`.
|
||||
///
|
||||
/// It prints all diagnostics in an implementation-defined format.
|
||||
class stderr_diagnostic_logger final : public diagnostic_logger
|
||||
{
|
||||
public:
|
||||
using diagnostic_logger::diagnostic_logger;
|
||||
|
||||
private:
|
||||
bool do_log(const char* source, const diagnostic& d) const override;
|
||||
};
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_DIAGNOSTIC_LOGGER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -11,252 +11,254 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
class libclang_compile_config;
|
||||
class libclang_compilation_database;
|
||||
class libclang_compile_config;
|
||||
class libclang_compilation_database;
|
||||
|
||||
namespace detail
|
||||
namespace detail
|
||||
{
|
||||
struct libclang_compile_config_access
|
||||
{
|
||||
struct libclang_compile_config_access
|
||||
{
|
||||
static const std::string& clang_binary(const libclang_compile_config& config);
|
||||
static const std::string& clang_binary(const libclang_compile_config& config);
|
||||
|
||||
static int clang_version(const libclang_compile_config& config);
|
||||
static int clang_version(const libclang_compile_config& config);
|
||||
|
||||
static const std::vector<std::string>& flags(const libclang_compile_config& config);
|
||||
static const std::vector<std::string>& flags(const libclang_compile_config& config);
|
||||
|
||||
static bool write_preprocessed(const libclang_compile_config& config);
|
||||
static bool write_preprocessed(const libclang_compile_config& config);
|
||||
|
||||
static bool fast_preprocessing(const libclang_compile_config& config);
|
||||
static bool fast_preprocessing(const libclang_compile_config& config);
|
||||
|
||||
static bool remove_comments_in_macro(const libclang_compile_config& config);
|
||||
};
|
||||
|
||||
void for_each_file(const libclang_compilation_database& database, void* user_data,
|
||||
void (*callback)(void*, std::string));
|
||||
} // namespace detail
|
||||
|
||||
/// The exception thrown when a fatal parse error occurs.
|
||||
class libclang_error final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it with a message.
|
||||
libclang_error(std::string msg) : std::runtime_error(std::move(msg)) {}
|
||||
static bool remove_comments_in_macro(const libclang_compile_config& config);
|
||||
};
|
||||
|
||||
/// A compilation database.
|
||||
///
|
||||
/// This represents a `compile_commands.json` file,
|
||||
/// which stores all the commands needed to compile a set of files.
|
||||
/// It can be generated by CMake using the `CMAKE_EXPORT_COMPILE_COMMANDS` option.
|
||||
class libclang_compilation_database
|
||||
void for_each_file(const libclang_compilation_database& database, void* user_data,
|
||||
void (*callback)(void*, std::string));
|
||||
} // namespace detail
|
||||
|
||||
/// The exception thrown when a fatal parse error occurs.
|
||||
class libclang_error final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it with a message.
|
||||
libclang_error(std::string msg) : std::runtime_error(std::move(msg)) {}
|
||||
};
|
||||
|
||||
/// A compilation database.
|
||||
///
|
||||
/// This represents a `compile_commands.json` file,
|
||||
/// which stores all the commands needed to compile a set of files.
|
||||
/// It can be generated by CMake using the `CMAKE_EXPORT_COMPILE_COMMANDS` option.
|
||||
class libclang_compilation_database
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it giving the directory where the `compile_commands.json` file is located.
|
||||
/// \throws `libclang_error` if the database could not be loaded or found.
|
||||
libclang_compilation_database(const std::string& build_directory);
|
||||
|
||||
libclang_compilation_database(libclang_compilation_database&& other)
|
||||
: database_(other.database_)
|
||||
{
|
||||
public:
|
||||
/// \effects Creates it giving the directory where the `compile_commands.json` file is located.
|
||||
/// \throws `libclang_error` if the database could not be loaded or found.
|
||||
libclang_compilation_database(const std::string& build_directory);
|
||||
|
||||
libclang_compilation_database(libclang_compilation_database&& other)
|
||||
: database_(other.database_)
|
||||
{
|
||||
other.database_ = nullptr;
|
||||
}
|
||||
|
||||
~libclang_compilation_database();
|
||||
|
||||
libclang_compilation_database& operator=(libclang_compilation_database&& other)
|
||||
{
|
||||
libclang_compilation_database tmp(std::move(other));
|
||||
std::swap(tmp.database_, database_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the database contains information about the given file.
|
||||
/// \group has_config
|
||||
bool has_config(const char* file_name) const;
|
||||
|
||||
/// \group has_config
|
||||
bool has_config(const std::string& file_name) const
|
||||
{
|
||||
return has_config(file_name.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
using database = void*;
|
||||
database database_;
|
||||
|
||||
friend libclang_compile_config;
|
||||
friend void detail::for_each_file(const libclang_compilation_database& database,
|
||||
void* user_data, void (*callback)(void*, std::string));
|
||||
};
|
||||
|
||||
/// Compilation config for the [cppast::libclang_parser]().
|
||||
class libclang_compile_config final : public compile_config
|
||||
{
|
||||
public:
|
||||
/// Creates the default configuration.
|
||||
///
|
||||
/// \effects It will set the clang binary determined by the build system,
|
||||
/// as well as the libclang system include directory determined by the build system.
|
||||
/// It will also define `__cppast__` with the value `"libclang"` as well as `__cppast_major__` and `__cppast_minor__`.
|
||||
libclang_compile_config();
|
||||
|
||||
/// Creates the configuration stored in the database.
|
||||
///
|
||||
/// \effects It will use the options found in the database for the specified file.
|
||||
/// This does not necessarily need to match the file that is going to be parsed,
|
||||
/// but it should.
|
||||
/// It will also add the default configuration options.
|
||||
/// \notes Header files are not included in the compilation database,
|
||||
/// you need to pass in the file name of the corresponding source file,
|
||||
/// if you want to parse one.
|
||||
/// \notes It will only consider options you could also set by the other functions.
|
||||
/// \notes The file key will include the specified directory in the JSON, if it is not a full path.
|
||||
libclang_compile_config(const libclang_compilation_database& database,
|
||||
const std::string& file);
|
||||
|
||||
libclang_compile_config(const libclang_compile_config& other) = default;
|
||||
libclang_compile_config& operator=(const libclang_compile_config& other) = default;
|
||||
|
||||
/// \effects Sets the path to the location of the `clang++` binary and the version of that binary.
|
||||
/// \notes It will be used for preprocessing.
|
||||
void set_clang_binary(std::string binary, int major, int minor, int patch)
|
||||
{
|
||||
clang_binary_ = std::move(binary);
|
||||
clang_version_ = major * 10000 + minor * 100 + patch;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not the preprocessed file will be written out.
|
||||
/// Default value is `false`.
|
||||
void write_preprocessed(bool b) noexcept
|
||||
{
|
||||
write_preprocessed_ = b;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not the fast preprocessor is enabled.
|
||||
/// Default value is `false`.
|
||||
/// \notes The fast preprocessor gets a list of all macros that are defined in the translation unit,
|
||||
/// then preprocesses it without resolving includes but manually defining the list of macros to ensure correctness.
|
||||
/// Later stages will use the includes again.
|
||||
/// This hack breaks if you define the same macro multiple times in the file being parsed (headers don't matter)
|
||||
/// or you rely on the order of macro directives.
|
||||
/// \notes If this option is `true`, the full file name of include directives is not available,
|
||||
/// just the name as written in the source code.
|
||||
void fast_preprocessing(bool b) noexcept
|
||||
{
|
||||
fast_preprocessing_ = b;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not documentation comments generated by macros are removed.
|
||||
/// Default value is `false`.
|
||||
/// \notes If this leads to an error due to preprocessing and comments, you have to enable it.
|
||||
/// \notes If this is `true`, `clang` will be invoked with `-CC`, otherwise `-C`.
|
||||
void remove_comments_in_macro(bool b) noexcept
|
||||
{
|
||||
remove_comments_in_macro_ = b;
|
||||
}
|
||||
|
||||
private:
|
||||
void do_set_flags(cpp_standard standard, compile_flags flags) override;
|
||||
|
||||
void do_add_include_dir(std::string path) override;
|
||||
|
||||
void do_add_macro_definition(std::string name, std::string definition) override;
|
||||
|
||||
void do_remove_macro_definition(std::string name) override;
|
||||
|
||||
const char* do_get_name() const noexcept override
|
||||
{
|
||||
return "libclang";
|
||||
}
|
||||
|
||||
std::string clang_binary_;
|
||||
int clang_version_;
|
||||
bool write_preprocessed_ : 1;
|
||||
bool fast_preprocessing_ : 1;
|
||||
bool remove_comments_in_macro_ : 1;
|
||||
|
||||
friend detail::libclang_compile_config_access;
|
||||
};
|
||||
|
||||
/// Finds a configuration for a given file.
|
||||
///
|
||||
/// \returns If the database contains a configuration for the given file, returns that configuration.
|
||||
/// Otherwise removes the file extension of the file and tries the same procedure
|
||||
/// for common C++ header and source file extensions.
|
||||
/// \notes This function is intended to be used as the basis for a `get_config` function of [cppast::parse_files](standardese://cppast::parse_files_basic/).
|
||||
type_safe::optional<libclang_compile_config> find_config_for(
|
||||
const libclang_compilation_database& database, std::string file_name);
|
||||
|
||||
/// A parser that uses libclang.
|
||||
class libclang_parser final : public parser
|
||||
{
|
||||
public:
|
||||
using config = libclang_compile_config;
|
||||
|
||||
/// \effects Creates a parser using the default logger.
|
||||
libclang_parser();
|
||||
|
||||
/// \effects Creates a parser that will log error messages using the specified logger.
|
||||
explicit libclang_parser(type_safe::object_ref<const diagnostic_logger> logger);
|
||||
|
||||
~libclang_parser() noexcept override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const override;
|
||||
|
||||
struct impl;
|
||||
std::unique_ptr<impl> pimpl_;
|
||||
};
|
||||
|
||||
/// Parses multiple files using a [cppast::libclang_parser]() and a compilation database.
|
||||
///
|
||||
/// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser and file names,
|
||||
/// and a `get_config` function using [cppast::find_config_for]().
|
||||
///
|
||||
/// \throws [cppast::libclang_error]() if no configuration for a given file could be found in the database.
|
||||
///
|
||||
/// \requires `FileParser` must use the libclang parser.
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser, class Range>
|
||||
void parse_files(FileParser& parser, Range&& file_names,
|
||||
const libclang_compilation_database& database)
|
||||
{
|
||||
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
|
||||
"must use the libclang parser");
|
||||
parse_files(parser, std::forward<Range>(file_names), [&](const std::string& file) {
|
||||
auto config = find_config_for(database, file);
|
||||
if (!config)
|
||||
throw libclang_error("unable to find configuration for file '" + file + "'");
|
||||
return config.value();
|
||||
});
|
||||
other.database_ = nullptr;
|
||||
}
|
||||
|
||||
/// Parses the files specified in a compilation database using a [cppast::libclang_parser]().
|
||||
///
|
||||
/// \effects For each file specified in a compilation database,
|
||||
/// uses the `FileParser` to parse the file with the configuration specified in the database.
|
||||
///
|
||||
/// \requires `FileParser` must have the same requirements as for [cppast::parse_files](standardese://parse_files_basic/).
|
||||
/// It must also use the libclang parser,
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser>
|
||||
void parse_database(FileParser& parser, const libclang_compilation_database& database)
|
||||
{
|
||||
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
|
||||
"must use the libclang parser");
|
||||
struct data_t
|
||||
{
|
||||
FileParser& parser;
|
||||
const libclang_compilation_database& database;
|
||||
} data{parser, database};
|
||||
detail::for_each_file(database, &data, [](void* ptr, std::string file) {
|
||||
auto& data = *static_cast<data_t*>(ptr);
|
||||
~libclang_compilation_database();
|
||||
|
||||
libclang_compile_config config(data.database, file);
|
||||
data.parser.parse(std::move(file), std::move(config));
|
||||
});
|
||||
libclang_compilation_database& operator=(libclang_compilation_database&& other)
|
||||
{
|
||||
libclang_compilation_database tmp(std::move(other));
|
||||
std::swap(tmp.database_, database_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \returns Whether or not the database contains information about the given file.
|
||||
/// \group has_config
|
||||
bool has_config(const char* file_name) const;
|
||||
|
||||
/// \group has_config
|
||||
bool has_config(const std::string& file_name) const
|
||||
{
|
||||
return has_config(file_name.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
using database = void*;
|
||||
database database_;
|
||||
|
||||
friend libclang_compile_config;
|
||||
friend void detail::for_each_file(const libclang_compilation_database& database,
|
||||
void* user_data, void (*callback)(void*, std::string));
|
||||
};
|
||||
|
||||
/// Compilation config for the [cppast::libclang_parser]().
|
||||
class libclang_compile_config final : public compile_config
|
||||
{
|
||||
public:
|
||||
/// Creates the default configuration.
|
||||
///
|
||||
/// \effects It will set the clang binary determined by the build system,
|
||||
/// as well as the libclang system include directory determined by the build system.
|
||||
/// It will also define `__cppast__` with the value `"libclang"` as well as `__cppast_major__`
|
||||
/// and `__cppast_minor__`.
|
||||
libclang_compile_config();
|
||||
|
||||
/// Creates the configuration stored in the database.
|
||||
///
|
||||
/// \effects It will use the options found in the database for the specified file.
|
||||
/// This does not necessarily need to match the file that is going to be parsed,
|
||||
/// but it should.
|
||||
/// It will also add the default configuration options.
|
||||
/// \notes Header files are not included in the compilation database,
|
||||
/// you need to pass in the file name of the corresponding source file,
|
||||
/// if you want to parse one.
|
||||
/// \notes It will only consider options you could also set by the other functions.
|
||||
/// \notes The file key will include the specified directory in the JSON, if it is not a full
|
||||
/// path.
|
||||
libclang_compile_config(const libclang_compilation_database& database, const std::string& file);
|
||||
|
||||
libclang_compile_config(const libclang_compile_config& other) = default;
|
||||
libclang_compile_config& operator=(const libclang_compile_config& other) = default;
|
||||
|
||||
/// \effects Sets the path to the location of the `clang++` binary and the version of that
|
||||
/// binary. \notes It will be used for preprocessing.
|
||||
void set_clang_binary(std::string binary, int major, int minor, int patch)
|
||||
{
|
||||
clang_binary_ = std::move(binary);
|
||||
clang_version_ = major * 10000 + minor * 100 + patch;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not the preprocessed file will be written out.
|
||||
/// Default value is `false`.
|
||||
void write_preprocessed(bool b) noexcept
|
||||
{
|
||||
write_preprocessed_ = b;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not the fast preprocessor is enabled.
|
||||
/// Default value is `false`.
|
||||
/// \notes The fast preprocessor gets a list of all macros that are defined in the translation
|
||||
/// unit, then preprocesses it without resolving includes but manually defining the list of
|
||||
/// macros to ensure correctness. Later stages will use the includes again. This hack breaks if
|
||||
/// you define the same macro multiple times in the file being parsed (headers don't matter) or
|
||||
/// you rely on the order of macro directives. \notes If this option is `true`, the full file
|
||||
/// name of include directives is not available, just the name as written in the source code.
|
||||
void fast_preprocessing(bool b) noexcept
|
||||
{
|
||||
fast_preprocessing_ = b;
|
||||
}
|
||||
|
||||
/// \effects Sets whether or not documentation comments generated by macros are removed.
|
||||
/// Default value is `false`.
|
||||
/// \notes If this leads to an error due to preprocessing and comments, you have to enable it.
|
||||
/// \notes If this is `true`, `clang` will be invoked with `-CC`, otherwise `-C`.
|
||||
void remove_comments_in_macro(bool b) noexcept
|
||||
{
|
||||
remove_comments_in_macro_ = b;
|
||||
}
|
||||
|
||||
private:
|
||||
void do_set_flags(cpp_standard standard, compile_flags flags) override;
|
||||
|
||||
void do_add_include_dir(std::string path) override;
|
||||
|
||||
void do_add_macro_definition(std::string name, std::string definition) override;
|
||||
|
||||
void do_remove_macro_definition(std::string name) override;
|
||||
|
||||
const char* do_get_name() const noexcept override
|
||||
{
|
||||
return "libclang";
|
||||
}
|
||||
|
||||
std::string clang_binary_;
|
||||
int clang_version_;
|
||||
bool write_preprocessed_ : 1;
|
||||
bool fast_preprocessing_ : 1;
|
||||
bool remove_comments_in_macro_ : 1;
|
||||
|
||||
friend detail::libclang_compile_config_access;
|
||||
};
|
||||
|
||||
/// Finds a configuration for a given file.
|
||||
///
|
||||
/// \returns If the database contains a configuration for the given file, returns that
|
||||
/// configuration. Otherwise removes the file extension of the file and tries the same procedure for
|
||||
/// common C++ header and source file extensions. \notes This function is intended to be used as the
|
||||
/// basis for a `get_config` function of
|
||||
/// [cppast::parse_files](standardese://cppast::parse_files_basic/).
|
||||
type_safe::optional<libclang_compile_config> find_config_for(
|
||||
const libclang_compilation_database& database, std::string file_name);
|
||||
|
||||
/// A parser that uses libclang.
|
||||
class libclang_parser final : public parser
|
||||
{
|
||||
public:
|
||||
using config = libclang_compile_config;
|
||||
|
||||
/// \effects Creates a parser using the default logger.
|
||||
libclang_parser();
|
||||
|
||||
/// \effects Creates a parser that will log error messages using the specified logger.
|
||||
explicit libclang_parser(type_safe::object_ref<const diagnostic_logger> logger);
|
||||
|
||||
~libclang_parser() noexcept override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const override;
|
||||
|
||||
struct impl;
|
||||
std::unique_ptr<impl> pimpl_;
|
||||
};
|
||||
|
||||
/// Parses multiple files using a [cppast::libclang_parser]() and a compilation database.
|
||||
///
|
||||
/// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser
|
||||
/// and file names, and a `get_config` function using [cppast::find_config_for]().
|
||||
///
|
||||
/// \throws [cppast::libclang_error]() if no configuration for a given file could be found in the
|
||||
/// database.
|
||||
///
|
||||
/// \requires `FileParser` must use the libclang parser.
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser, class Range>
|
||||
void parse_files(FileParser& parser, Range&& file_names,
|
||||
const libclang_compilation_database& database)
|
||||
{
|
||||
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
|
||||
"must use the libclang parser");
|
||||
parse_files(parser, std::forward<Range>(file_names), [&](const std::string& file) {
|
||||
auto config = find_config_for(database, file);
|
||||
if (!config)
|
||||
throw libclang_error("unable to find configuration for file '" + file + "'");
|
||||
return config.value();
|
||||
});
|
||||
}
|
||||
|
||||
/// Parses the files specified in a compilation database using a [cppast::libclang_parser]().
|
||||
///
|
||||
/// \effects For each file specified in a compilation database,
|
||||
/// uses the `FileParser` to parse the file with the configuration specified in the database.
|
||||
///
|
||||
/// \requires `FileParser` must have the same requirements as for
|
||||
/// [cppast::parse_files](standardese://parse_files_basic/). It must also use the libclang parser,
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser>
|
||||
void parse_database(FileParser& parser, const libclang_compilation_database& database)
|
||||
{
|
||||
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
|
||||
"must use the libclang parser");
|
||||
struct data_t
|
||||
{
|
||||
FileParser& parser;
|
||||
const libclang_compilation_database& database;
|
||||
} data{parser, database};
|
||||
detail::for_each_file(database, &data, [](void* ptr, std::string file) {
|
||||
auto& data = *static_cast<data_t*>(ptr);
|
||||
|
||||
libclang_compile_config config(data.database, file);
|
||||
data.parser.parse(std::move(file), std::move(config));
|
||||
});
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_LIBCLANG_PARSER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -10,232 +10,223 @@
|
|||
#include <cppast/compile_config.hpp>
|
||||
#include <cppast/cpp_file.hpp>
|
||||
#include <cppast/cpp_preprocessor.hpp>
|
||||
#include <cppast/diagnostic_logger.hpp>
|
||||
#include <cppast/diagnostic.hpp>
|
||||
#include <cppast/diagnostic_logger.hpp>
|
||||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_entity_index;
|
||||
class cpp_entity_index;
|
||||
|
||||
/// Base class for a parser.
|
||||
///
|
||||
/// It reads a C++ source file and creates the matching [cppast::cpp_file]().
|
||||
/// Derived classes can implement how the file is parsed.
|
||||
///
|
||||
/// \requires A derived class must provide an alias `config` which is the corresponding derived class of the [cppast::compile_config]().
|
||||
class parser
|
||||
/// Base class for a parser.
|
||||
///
|
||||
/// It reads a C++ source file and creates the matching [cppast::cpp_file]().
|
||||
/// Derived classes can implement how the file is parsed.
|
||||
///
|
||||
/// \requires A derived class must provide an alias `config` which is the corresponding derived
|
||||
/// class of the [cppast::compile_config]().
|
||||
class parser
|
||||
{
|
||||
public:
|
||||
parser(const parser&) = delete;
|
||||
parser& operator=(const parser&) = delete;
|
||||
|
||||
virtual ~parser() noexcept = default;
|
||||
|
||||
/// \effects Parses the given file.
|
||||
/// \returns The [cppast::cpp_file]() object describing it.
|
||||
/// It can be `nullptr`, if there was an error or the specified file already registered in the
|
||||
/// index. \requires The dynamic type of `config` must match the required config type. \notes
|
||||
/// This function is thread safe.
|
||||
std::unique_ptr<cpp_file> parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const
|
||||
{
|
||||
public:
|
||||
parser(const parser&) = delete;
|
||||
parser& operator=(const parser&) = delete;
|
||||
|
||||
virtual ~parser() noexcept = default;
|
||||
|
||||
/// \effects Parses the given file.
|
||||
/// \returns The [cppast::cpp_file]() object describing it.
|
||||
/// It can be `nullptr`, if there was an error or the specified file already registered in the index.
|
||||
/// \requires The dynamic type of `config` must match the required config type.
|
||||
/// \notes This function is thread safe.
|
||||
std::unique_ptr<cpp_file> parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const
|
||||
{
|
||||
return do_parse(idx, std::move(path), config);
|
||||
}
|
||||
|
||||
/// \returns Whether or not an error occurred during parsing.
|
||||
/// If that happens, the AST might be incomplete.
|
||||
bool error() const noexcept
|
||||
{
|
||||
return error_;
|
||||
}
|
||||
|
||||
/// \effects Resets the error state.
|
||||
void reset_error() noexcept
|
||||
{
|
||||
error_ = false;
|
||||
}
|
||||
|
||||
/// \returns A reference to the logger used.
|
||||
const diagnostic_logger& logger() const noexcept
|
||||
{
|
||||
return *logger_;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Creates it giving it a reference to the logger it uses.
|
||||
explicit parser(type_safe::object_ref<const diagnostic_logger> logger)
|
||||
: logger_(logger), error_(false)
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Sets the error state.
|
||||
/// This must be called when an error or critical diagnostic is logged and the AST is incomplete.
|
||||
void set_error() const noexcept
|
||||
{
|
||||
error_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \effects Parses the given file.
|
||||
/// \returns The [cppast::cpp_file]() object describing it.
|
||||
/// \requires The function must be thread safe.
|
||||
virtual std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const = 0;
|
||||
|
||||
type_safe::object_ref<const diagnostic_logger> logger_;
|
||||
mutable std::atomic<bool> error_;
|
||||
};
|
||||
|
||||
/// A simple `FileParser` that parses all files synchronously.
|
||||
///
|
||||
/// More advanced parsers could use a thread pool, for example.
|
||||
template <class Parser>
|
||||
class simple_file_parser
|
||||
{
|
||||
static_assert(std::is_base_of<cppast::parser, Parser>::value,
|
||||
"Parser must be derived from cppast::parser");
|
||||
|
||||
public:
|
||||
using parser = Parser;
|
||||
using config = typename Parser::config;
|
||||
|
||||
/// \effects Creates a file parser populating the given index
|
||||
/// and using the parser created by forwarding the given arguments.
|
||||
template <typename... Args>
|
||||
explicit simple_file_parser(type_safe::object_ref<const cpp_entity_index> idx,
|
||||
Args&&... args)
|
||||
: parser_(std::forward<Args>(args)...), idx_(idx)
|
||||
{
|
||||
}
|
||||
|
||||
/// \effects Parses the given file using the given configuration.
|
||||
/// \returns The parsed file or an empty optional, if a fatal error occurred.
|
||||
type_safe::optional_ref<const cpp_file> parse(std::string path, const config& c)
|
||||
{
|
||||
parser_.logger().log("simple file parser",
|
||||
diagnostic{"parsing file '" + path + "'", source_location(),
|
||||
severity::info});
|
||||
auto file = parser_.parse(*idx_, std::move(path), c);
|
||||
auto ptr = file.get();
|
||||
if (file)
|
||||
files_.push_back(std::move(file));
|
||||
return type_safe::opt_ref(ptr);
|
||||
}
|
||||
|
||||
/// \returns The result of [cppast::parser::error]().
|
||||
bool error() const noexcept
|
||||
{
|
||||
return parser_.error();
|
||||
}
|
||||
|
||||
/// \effects Calls [cppast::parser::reset_error]().
|
||||
void reset_error() noexcept
|
||||
{
|
||||
parser_.reset_error();
|
||||
}
|
||||
|
||||
/// \returns The index that is being populated.
|
||||
const cpp_entity_index& index() const noexcept
|
||||
{
|
||||
return *idx_;
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over all the files that have been parsed so far.
|
||||
/// \exclude return
|
||||
detail::iteratable_intrusive_list<cpp_file> files() const noexcept
|
||||
{
|
||||
return type_safe::ref(files_);
|
||||
}
|
||||
|
||||
private:
|
||||
Parser parser_;
|
||||
detail::intrusive_list<cpp_file> files_;
|
||||
type_safe::object_ref<const cpp_entity_index> idx_;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct std_begin
|
||||
{
|
||||
};
|
||||
struct adl_begin : std_begin
|
||||
{
|
||||
};
|
||||
struct member_begin : adl_begin
|
||||
{
|
||||
};
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(member_begin, Range&& r)
|
||||
-> decltype(std::forward<Range>(r).begin());
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(adl_begin, Range&& r) -> decltype(begin(std::forward<Range>(r)));
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(std_begin, Range&& r)
|
||||
-> decltype(std::begin(std::forward<Range>(r)));
|
||||
|
||||
template <class Range>
|
||||
using value_type = decltype(*get_value_type_impl(member_begin{}, std::declval<Range>()));
|
||||
} // namespace detail
|
||||
|
||||
/// Parses multiple files using a given `FileParser`.
|
||||
///
|
||||
/// \effects Will call the `parse()` function for each path specified in the `file_names`,
|
||||
/// using `get_confg` to determine the configuration.
|
||||
///
|
||||
/// \requires `FileParser` must be a class with the following members:
|
||||
/// * `parser` - A typedef for the parser being used to do the parsing.
|
||||
/// * `config` - The same as `parser::config`.
|
||||
/// * `parse(path, config)` - Parses the given file with the configuration using its parser.
|
||||
/// The parsing can be executed in a separated thread, but then a copy of the configuration and path must be created.
|
||||
/// \requires `Range` must be some type that can be iterated in a range-based for loop.
|
||||
/// \requires `Configuration` must be a function that returns a configuration of type `FileParser::config` when given a path.
|
||||
/// \unique_name parse_files_basic
|
||||
/// \synopsis_return void
|
||||
template <class FileParser, class Range, class Configuration>
|
||||
auto parse_files(FileParser& parser, Range&& file_names, const Configuration& get_config) ->
|
||||
typename std::enable_if<std::is_same<typename std::decay<decltype(get_config(
|
||||
std::declval<detail::value_type<Range>>()))>::type,
|
||||
typename FileParser::config>::value>::type
|
||||
{
|
||||
for (auto&& file : std::forward<Range>(file_names))
|
||||
{
|
||||
auto&& config = get_config(file);
|
||||
parser.parse(std::forward<decltype(file)>(file),
|
||||
std::forward<decltype(config)>(config));
|
||||
}
|
||||
return do_parse(idx, std::move(path), config);
|
||||
}
|
||||
|
||||
/// Parses multiple files using a given `FileParser` and configuration.
|
||||
/// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser and file names,
|
||||
/// and a function that returns the same configuration for each file.
|
||||
template <class FileParser, class Range>
|
||||
void parse_files(FileParser& parser, Range&& file_names, typename FileParser::config config)
|
||||
/// \returns Whether or not an error occurred during parsing.
|
||||
/// If that happens, the AST might be incomplete.
|
||||
bool error() const noexcept
|
||||
{
|
||||
parse_files(parser, std::forward<Range>(file_names),
|
||||
[&](const std::string&) { return config; });
|
||||
return error_;
|
||||
}
|
||||
|
||||
/// Parses all files included by `file`.
|
||||
/// \effects For each [cppast::cpp_include_directive]() in file it will parse the included file.
|
||||
template <class FileParser>
|
||||
std::size_t resolve_includes(FileParser& parser, const cpp_file& file,
|
||||
typename FileParser::config config)
|
||||
/// \effects Resets the error state.
|
||||
void reset_error() noexcept
|
||||
{
|
||||
auto count = 0u;
|
||||
for (auto& entity : file)
|
||||
{
|
||||
if (entity.kind() == cpp_include_directive::kind())
|
||||
{
|
||||
auto& include = static_cast<const cpp_include_directive&>(entity);
|
||||
parser.parse(include.full_path(), config);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
error_ = false;
|
||||
}
|
||||
|
||||
/// \returns A reference to the logger used.
|
||||
const diagnostic_logger& logger() const noexcept
|
||||
{
|
||||
return *logger_;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \effects Creates it giving it a reference to the logger it uses.
|
||||
explicit parser(type_safe::object_ref<const diagnostic_logger> logger)
|
||||
: logger_(logger), error_(false)
|
||||
{}
|
||||
|
||||
/// \effects Sets the error state.
|
||||
/// This must be called when an error or critical diagnostic is logged and the AST is
|
||||
/// incomplete.
|
||||
void set_error() const noexcept
|
||||
{
|
||||
error_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \effects Parses the given file.
|
||||
/// \returns The [cppast::cpp_file]() object describing it.
|
||||
/// \requires The function must be thread safe.
|
||||
virtual std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path,
|
||||
const compile_config& config) const = 0;
|
||||
|
||||
type_safe::object_ref<const diagnostic_logger> logger_;
|
||||
mutable std::atomic<bool> error_;
|
||||
};
|
||||
|
||||
/// A simple `FileParser` that parses all files synchronously.
|
||||
///
|
||||
/// More advanced parsers could use a thread pool, for example.
|
||||
template <class Parser>
|
||||
class simple_file_parser
|
||||
{
|
||||
static_assert(std::is_base_of<cppast::parser, Parser>::value,
|
||||
"Parser must be derived from cppast::parser");
|
||||
|
||||
public:
|
||||
using parser = Parser;
|
||||
using config = typename Parser::config;
|
||||
|
||||
/// \effects Creates a file parser populating the given index
|
||||
/// and using the parser created by forwarding the given arguments.
|
||||
template <typename... Args>
|
||||
explicit simple_file_parser(type_safe::object_ref<const cpp_entity_index> idx, Args&&... args)
|
||||
: parser_(std::forward<Args>(args)...), idx_(idx)
|
||||
{}
|
||||
|
||||
/// \effects Parses the given file using the given configuration.
|
||||
/// \returns The parsed file or an empty optional, if a fatal error occurred.
|
||||
type_safe::optional_ref<const cpp_file> parse(std::string path, const config& c)
|
||||
{
|
||||
parser_.logger().log("simple file parser", diagnostic{"parsing file '" + path + "'",
|
||||
source_location(), severity::info});
|
||||
auto file = parser_.parse(*idx_, std::move(path), c);
|
||||
auto ptr = file.get();
|
||||
if (file)
|
||||
files_.push_back(std::move(file));
|
||||
return type_safe::opt_ref(ptr);
|
||||
}
|
||||
|
||||
/// \returns The result of [cppast::parser::error]().
|
||||
bool error() const noexcept
|
||||
{
|
||||
return parser_.error();
|
||||
}
|
||||
|
||||
/// \effects Calls [cppast::parser::reset_error]().
|
||||
void reset_error() noexcept
|
||||
{
|
||||
parser_.reset_error();
|
||||
}
|
||||
|
||||
/// \returns The index that is being populated.
|
||||
const cpp_entity_index& index() const noexcept
|
||||
{
|
||||
return *idx_;
|
||||
}
|
||||
|
||||
/// \returns An iteratable object iterating over all the files that have been parsed so far.
|
||||
/// \exclude return
|
||||
detail::iteratable_intrusive_list<cpp_file> files() const noexcept
|
||||
{
|
||||
return type_safe::ref(files_);
|
||||
}
|
||||
|
||||
private:
|
||||
Parser parser_;
|
||||
detail::intrusive_list<cpp_file> files_;
|
||||
type_safe::object_ref<const cpp_entity_index> idx_;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct std_begin
|
||||
{};
|
||||
struct adl_begin : std_begin
|
||||
{};
|
||||
struct member_begin : adl_begin
|
||||
{};
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(member_begin, Range&& r) -> decltype(std::forward<Range>(r).begin());
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(adl_begin, Range&& r) -> decltype(begin(std::forward<Range>(r)));
|
||||
|
||||
template <class Range>
|
||||
auto get_value_type_impl(std_begin, Range&& r) -> decltype(std::begin(std::forward<Range>(r)));
|
||||
|
||||
template <class Range>
|
||||
using value_type = decltype(*get_value_type_impl(member_begin{}, std::declval<Range>()));
|
||||
} // namespace detail
|
||||
|
||||
/// Parses multiple files using a given `FileParser`.
|
||||
///
|
||||
/// \effects Will call the `parse()` function for each path specified in the `file_names`,
|
||||
/// using `get_confg` to determine the configuration.
|
||||
///
|
||||
/// \requires `FileParser` must be a class with the following members:
|
||||
/// * `parser` - A typedef for the parser being used to do the parsing.
|
||||
/// * `config` - The same as `parser::config`.
|
||||
/// * `parse(path, config)` - Parses the given file with the configuration using its parser.
|
||||
/// The parsing can be executed in a separated thread, but then a copy of the configuration and path
|
||||
/// must be created. \requires `Range` must be some type that can be iterated in a range-based for
|
||||
/// loop. \requires `Configuration` must be a function that returns a configuration of type
|
||||
/// `FileParser::config` when given a path. \unique_name parse_files_basic \synopsis_return void
|
||||
template <class FileParser, class Range, class Configuration>
|
||||
auto parse_files(FileParser& parser, Range&& file_names, const Configuration& get_config) ->
|
||||
typename std::enable_if<std::is_same<
|
||||
typename std::decay<decltype(get_config(std::declval<detail::value_type<Range>>()))>::type,
|
||||
typename FileParser::config>::value>::type
|
||||
{
|
||||
for (auto&& file : std::forward<Range>(file_names))
|
||||
{
|
||||
auto&& config = get_config(file);
|
||||
parser.parse(std::forward<decltype(file)>(file), std::forward<decltype(config)>(config));
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses multiple files using a given `FileParser` and configuration.
|
||||
/// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser
|
||||
/// and file names, and a function that returns the same configuration for each file.
|
||||
template <class FileParser, class Range>
|
||||
void parse_files(FileParser& parser, Range&& file_names, typename FileParser::config config)
|
||||
{
|
||||
parse_files(parser, std::forward<Range>(file_names),
|
||||
[&](const std::string&) { return config; });
|
||||
}
|
||||
|
||||
/// Parses all files included by `file`.
|
||||
/// \effects For each [cppast::cpp_include_directive]() in file it will parse the included file.
|
||||
template <class FileParser>
|
||||
std::size_t resolve_includes(FileParser& parser, const cpp_file& file,
|
||||
typename FileParser::config config)
|
||||
{
|
||||
auto count = 0u;
|
||||
for (auto& entity : file)
|
||||
{
|
||||
if (entity.kind() == cpp_include_directive::kind())
|
||||
{
|
||||
auto& include = static_cast<const cpp_include_directive&>(entity);
|
||||
parser.parse(include.full_path(), config);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_PARSER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -13,231 +13,230 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
/// Information about the state of a visit operation.
|
||||
struct visitor_info
|
||||
/// Information about the state of a visit operation.
|
||||
struct visitor_info
|
||||
{
|
||||
enum event_type
|
||||
{
|
||||
enum event_type
|
||||
{
|
||||
leaf_entity, //< Callback called for a leaf entity without children.
|
||||
/// If callback returns `false`, visit operation will be aborted.
|
||||
leaf_entity, //< Callback called for a leaf entity without children.
|
||||
/// If callback returns `false`, visit operation will be aborted.
|
||||
|
||||
container_entity_enter, //< Callback called for a container entity before the children.
|
||||
/// If callback returns `false`, none of the children will be visited,
|
||||
/// going immediately to the exit event.
|
||||
container_entity_exit, //< Callback called for a container entity after the children.
|
||||
/// If callback returns `false`, visit operation will be aborted.
|
||||
} event;
|
||||
container_entity_enter, //< Callback called for a container entity before the children.
|
||||
/// If callback returns `false`, none of the children will be visited,
|
||||
/// going immediately to the exit event.
|
||||
container_entity_exit, //< Callback called for a container entity after the children.
|
||||
/// If callback returns `false`, visit operation will be aborted.
|
||||
} event;
|
||||
|
||||
cpp_access_specifier_kind access; //< The current access specifier.
|
||||
cpp_access_specifier_kind access; //< The current access specifier.
|
||||
|
||||
/// True when the current entity is the last child of the visited parent entity.
|
||||
/// \notes It will always be `false` for the initial entity.
|
||||
bool last_child;
|
||||
/// True when the current entity is the last child of the visited parent entity.
|
||||
/// \notes It will always be `false` for the initial entity.
|
||||
bool last_child;
|
||||
|
||||
/// \returns `true` if the entity was not visited already.
|
||||
bool is_new_entity() const noexcept
|
||||
{
|
||||
return event != container_entity_exit;
|
||||
}
|
||||
|
||||
/// \returns `true` if the entity was visited already.
|
||||
bool is_old_entity() const noexcept
|
||||
{
|
||||
return !is_new_entity();
|
||||
}
|
||||
};
|
||||
|
||||
/// A more expressive way to specify the return of a visit operation.
|
||||
enum visitor_result : bool
|
||||
/// \returns `true` if the entity was not visited already.
|
||||
bool is_new_entity() const noexcept
|
||||
{
|
||||
/// Visit should continue.
|
||||
/// \group continue
|
||||
continue_visit = true,
|
||||
return event != container_entity_exit;
|
||||
}
|
||||
|
||||
/// \group continue
|
||||
continue_visit_children = true,
|
||||
|
||||
/// Visit should not visit the children.
|
||||
/// \notes This only happens when the event is [cppast::visitor_info::container_entity_enter]().
|
||||
continue_visit_no_children = false,
|
||||
|
||||
/// Visit should be aborted.
|
||||
/// \notes This only happens when the event is not [cppast::visitor_info::container_entity_enter]().
|
||||
abort_visit = false,
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
/// \returns `true` if the entity was visited already.
|
||||
bool is_old_entity() const noexcept
|
||||
{
|
||||
using visitor_callback_t = bool (*)(void* mem, const cpp_entity&, visitor_info info);
|
||||
return !is_new_entity();
|
||||
}
|
||||
};
|
||||
|
||||
struct visitor_info_void
|
||||
{
|
||||
};
|
||||
struct visitor_info_bool : visitor_info_void
|
||||
{
|
||||
};
|
||||
/// A more expressive way to specify the return of a visit operation.
|
||||
enum visitor_result : bool
|
||||
{
|
||||
/// Visit should continue.
|
||||
/// \group continue
|
||||
continue_visit = true,
|
||||
|
||||
template <typename Func>
|
||||
visitor_callback_t get_visitor_callback(
|
||||
visitor_info_bool, decltype(std::declval<Func>()(std::declval<const cpp_entity&>(),
|
||||
visitor_info{})) = true)
|
||||
{
|
||||
return [](void* mem, const cpp_entity& e, visitor_info info) {
|
||||
auto& func = *static_cast<Func*>(mem);
|
||||
return func(e, info);
|
||||
};
|
||||
}
|
||||
/// \group continue
|
||||
continue_visit_children = true,
|
||||
|
||||
template <typename Func>
|
||||
visitor_callback_t get_visitor_callback(
|
||||
visitor_info_void,
|
||||
decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{}),
|
||||
0) = 0)
|
||||
{
|
||||
return [](void* mem, const cpp_entity& e, visitor_info info) {
|
||||
auto& func = *static_cast<Func*>(mem);
|
||||
func(e, info);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
/// Visit should not visit the children.
|
||||
/// \notes This only happens when the event is [cppast::visitor_info::container_entity_enter]().
|
||||
continue_visit_no_children = false,
|
||||
|
||||
template <typename Func>
|
||||
visitor_callback_t get_visitor_callback()
|
||||
{
|
||||
return get_visitor_callback<Func>(visitor_info_bool{});
|
||||
}
|
||||
/// Visit should be aborted.
|
||||
/// \notes This only happens when the event is not
|
||||
/// [cppast::visitor_info::container_entity_enter]().
|
||||
abort_visit = false,
|
||||
};
|
||||
|
||||
bool visit(const cpp_entity& e, visitor_callback_t cb, void* functor,
|
||||
cpp_access_specifier_kind cur_access, bool last_child);
|
||||
} // namespace detail
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
using visitor_callback_t = bool (*)(void* mem, const cpp_entity&, visitor_info info);
|
||||
|
||||
struct visitor_info_void
|
||||
{};
|
||||
struct visitor_info_bool : visitor_info_void
|
||||
{};
|
||||
|
||||
/// Visits a [cppast::cpp_entity]() and children.
|
||||
///
|
||||
/// \effects It will invoke the callback - the visitor - for the current entity and children,
|
||||
/// as controlled by the [cppast::visitor_result]().
|
||||
/// The visitor is given a reference to the currently visited entity and the [cppast::visitor_info]().
|
||||
///
|
||||
/// \requires The visitor must be callable as specified and must either return `bool` or nothing.
|
||||
/// If it returns nothing, a return value [cppast::visitor_result::continue_visit]() is assumed.
|
||||
template <typename Func>
|
||||
void visit(const cpp_entity& e, Func f)
|
||||
visitor_callback_t get_visitor_callback(
|
||||
visitor_info_bool,
|
||||
decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{})) = true)
|
||||
{
|
||||
detail::visit(e, detail::get_visitor_callback<Func>(), &f, cpp_public, false);
|
||||
return [](void* mem, const cpp_entity& e, visitor_info info) {
|
||||
auto& func = *static_cast<Func*>(mem);
|
||||
return func(e, info);
|
||||
};
|
||||
}
|
||||
|
||||
/// The result of a visitor filter operation.
|
||||
enum class visit_filter
|
||||
template <typename Func>
|
||||
visitor_callback_t get_visitor_callback(
|
||||
visitor_info_void,
|
||||
decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{}), 0) = 0)
|
||||
{
|
||||
include = true, //< The entity is included.
|
||||
exclude = false, //< The entity is excluded and will not be visited.
|
||||
exclude_and_children =
|
||||
2, //< The entity and all direct children are excluded and will not be visited.
|
||||
};
|
||||
return [](void* mem, const cpp_entity& e, visitor_info info) {
|
||||
auto& func = *static_cast<Func*>(mem);
|
||||
func(e, info);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
template <typename Func>
|
||||
visitor_callback_t get_visitor_callback()
|
||||
{
|
||||
using visitor_filter_t = visit_filter (*)(const cpp_entity&);
|
||||
return get_visitor_callback<Func>(visitor_info_bool{});
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
auto invoke_visit_filter(int, Filter f, const cpp_entity& e,
|
||||
cpp_access_specifier_kind access)
|
||||
-> decltype(static_cast<visit_filter>(f(e, access)))
|
||||
bool visit(const cpp_entity& e, visitor_callback_t cb, void* functor,
|
||||
cpp_access_specifier_kind cur_access, bool last_child);
|
||||
} // namespace detail
|
||||
|
||||
/// Visits a [cppast::cpp_entity]() and children.
|
||||
///
|
||||
/// \effects It will invoke the callback - the visitor - for the current entity and children,
|
||||
/// as controlled by the [cppast::visitor_result]().
|
||||
/// The visitor is given a reference to the currently visited entity and the
|
||||
/// [cppast::visitor_info]().
|
||||
///
|
||||
/// \requires The visitor must be callable as specified and must either return `bool` or nothing.
|
||||
/// If it returns nothing, a return value [cppast::visitor_result::continue_visit]() is assumed.
|
||||
template <typename Func>
|
||||
void visit(const cpp_entity& e, Func f)
|
||||
{
|
||||
detail::visit(e, detail::get_visitor_callback<Func>(), &f, cpp_public, false);
|
||||
}
|
||||
|
||||
/// The result of a visitor filter operation.
|
||||
enum class visit_filter
|
||||
{
|
||||
include = true, //< The entity is included.
|
||||
exclude = false, //< The entity is excluded and will not be visited.
|
||||
exclude_and_children
|
||||
= 2, //< The entity and all direct children are excluded and will not be visited.
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
using visitor_filter_t = visit_filter (*)(const cpp_entity&);
|
||||
|
||||
template <typename Filter>
|
||||
auto invoke_visit_filter(int, Filter f, const cpp_entity& e, cpp_access_specifier_kind access)
|
||||
-> decltype(static_cast<visit_filter>(f(e, access)))
|
||||
{
|
||||
return static_cast<visit_filter>(f(e, access));
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
auto invoke_visit_filter(short, Filter f, const cpp_entity& e, cpp_access_specifier_kind)
|
||||
-> decltype(static_cast<visit_filter>(f(e)))
|
||||
{
|
||||
return static_cast<visit_filter>(f(e));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Visits a [cppast::cpp_entity]() and children that pass a given filter.
|
||||
///
|
||||
/// \effects It behaves like the non-filtered visit except it will only invoke the visitor for
|
||||
/// entities that match the filter. The filter is a predicate that will be invoked with the current
|
||||
/// entity and access specifier first and the result converted to [cppast::visit_filter](). Visit
|
||||
/// will behave accordingly.
|
||||
///
|
||||
/// \requires The visitor must be as specified for the other overload.
|
||||
/// The filter must be a function taking a [cppast::cpp_entity]() as first parameter and optionally
|
||||
/// a [cppast::cpp_access_specifier_kind]() as second. It must return a `bool` or a
|
||||
/// [cppast::visit_filter]().
|
||||
template <typename Func, typename Filter>
|
||||
void visit(const cpp_entity& e, Filter filter, Func f)
|
||||
{
|
||||
visit(e, [&](const cpp_entity& e, const visitor_info& info) -> bool {
|
||||
auto result = detail::invoke_visit_filter(0, filter, e, info.access);
|
||||
switch (result)
|
||||
{
|
||||
return static_cast<visit_filter>(f(e, access));
|
||||
}
|
||||
|
||||
template <typename Filter>
|
||||
auto invoke_visit_filter(short, Filter f, const cpp_entity& e, cpp_access_specifier_kind)
|
||||
-> decltype(static_cast<visit_filter>(f(e)))
|
||||
{
|
||||
return static_cast<visit_filter>(f(e));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Visits a [cppast::cpp_entity]() and children that pass a given filter.
|
||||
///
|
||||
/// \effects It behaves like the non-filtered visit except it will only invoke the visitor for entities that match the filter.
|
||||
/// The filter is a predicate that will be invoked with the current entity and access specifier first and the result converted to [cppast::visit_filter]().
|
||||
/// Visit will behave accordingly.
|
||||
///
|
||||
/// \requires The visitor must be as specified for the other overload.
|
||||
/// The filter must be a function taking a [cppast::cpp_entity]() as first parameter and optionally a [cppast::cpp_access_specifier_kind]() as second.
|
||||
/// It must return a `bool` or a [cppast::visit_filter]().
|
||||
template <typename Func, typename Filter>
|
||||
void visit(const cpp_entity& e, Filter filter, Func f)
|
||||
{
|
||||
visit(e, [&](const cpp_entity& e, const visitor_info& info) -> bool {
|
||||
auto result = detail::invoke_visit_filter(0, filter, e, info.access);
|
||||
switch (result)
|
||||
{
|
||||
case visit_filter::include:
|
||||
return detail::get_visitor_callback<Func>()(&f, e, info);
|
||||
case visit_filter::exclude:
|
||||
return continue_visit;
|
||||
case visit_filter::exclude_and_children:
|
||||
// exclude children if entering
|
||||
if (info.event == visitor_info::container_entity_enter)
|
||||
return continue_visit_no_children;
|
||||
else
|
||||
return continue_visit;
|
||||
}
|
||||
case visit_filter::include:
|
||||
return detail::get_visitor_callback<Func>()(&f, e, info);
|
||||
case visit_filter::exclude:
|
||||
return continue_visit;
|
||||
});
|
||||
}
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
template <cpp_entity_kind... K>
|
||||
bool has_one_of_kind(const cpp_entity& e)
|
||||
{
|
||||
static_assert(sizeof...(K) > 0, "At least one entity kind must be specified");
|
||||
bool result = false;
|
||||
|
||||
// poor men's fold
|
||||
int dummy[]{(result |= (K == e.kind()), 0)...};
|
||||
(void)dummy;
|
||||
|
||||
return result;
|
||||
case visit_filter::exclude_and_children:
|
||||
// exclude children if entering
|
||||
if (info.event == visitor_info::container_entity_enter)
|
||||
return continue_visit_no_children;
|
||||
else
|
||||
return continue_visit;
|
||||
}
|
||||
} // namespace detail
|
||||
return continue_visit;
|
||||
});
|
||||
}
|
||||
|
||||
/// Generates a blacklist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having one of the specified kinds.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t blacklist()
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
template <cpp_entity_kind... K>
|
||||
bool has_one_of_kind(const cpp_entity& e)
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude :
|
||||
visit_filter::include;
|
||||
};
|
||||
}
|
||||
static_assert(sizeof...(K) > 0, "At least one entity kind must be specified");
|
||||
bool result = false;
|
||||
|
||||
/// Generates a blacklist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having one of the specified kinds and children of those entities.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t blacklist_and_children()
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude_and_children :
|
||||
visit_filter::include;
|
||||
};
|
||||
}
|
||||
// poor men's fold
|
||||
int dummy[]{(result |= (K == e.kind()), 0)...};
|
||||
(void)dummy;
|
||||
|
||||
/// Generates a whitelist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having not one of the specified kinds.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t whitelist()
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::include :
|
||||
visit_filter::exclude;
|
||||
};
|
||||
return result;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Generates a blacklist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having one of the specified kinds.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t blacklist()
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude : visit_filter::include;
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a blacklist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having one of the specified kinds and
|
||||
/// children of those entities.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t blacklist_and_children()
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude_and_children
|
||||
: visit_filter::include;
|
||||
};
|
||||
}
|
||||
|
||||
/// Generates a whitelist visitor filter.
|
||||
///
|
||||
/// \returns A visitor filter that excludes all entities having not one of the specified kinds.
|
||||
template <cpp_entity_kind... Kinds>
|
||||
detail::visitor_filter_t whitelist()
|
||||
{
|
||||
return [](const cpp_entity& e) {
|
||||
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::include : visit_filter::exclude;
|
||||
};
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_VISITOR_HPP_INCLUDED
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue