diff --git a/include/cppast/cpp_attribute.hpp b/include/cppast/cpp_attribute.hpp new file mode 100644 index 0000000..d301107 --- /dev/null +++ b/include/cppast/cpp_attribute.hpp @@ -0,0 +1,130 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED +#define CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED + +#include +#include + +#include + +#include + +namespace cppast +{ + /// The known C++ attributes. + enum class cpp_attribute_kind + { + alignas_, + carries_dependency, + deprecated, + fallthrough, + maybe_unused, + nodiscard, + noreturn, + + unknown, //< An unknown attribute. + }; + + namespace detail + { + inline const char* get_attribute_name(cpp_attribute_kind kind) + { + switch (kind) + { + case cpp_attribute_kind::alignas_: + return "alignas"; + case cpp_attribute_kind::carries_dependency: + return "carries_dependency"; + case cpp_attribute_kind::deprecated: + return "deprecated"; + case cpp_attribute_kind::fallthrough: + return "fallthrough"; + case cpp_attribute_kind::maybe_unused: + return "maybe_unused"; + case cpp_attribute_kind::nodiscard: + return "nodiscard"; + case cpp_attribute_kind::noreturn: + return "noreturn"; + + case cpp_attribute_kind::unknown: + return "unknown"; + } + } + } // namespace detail + + /// 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 arguments) + : cpp_attribute(type_safe::nullopt, detail::get_attribute_name(kind), std::move(arguments), + false) + { + kind_ = kind; + } + + /// \effects Creates an unknown attribute giving it the optional scope, names, arguments and whether it is variadic. + cpp_attribute(type_safe::optional scope, std::string name, + type_safe::optional 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 + { + return kind_; + } + + /// \returns The name of the attribute. + const std::string& name() const noexcept + { + return name_; + } + + /// \returns The scope of the attribute, if there is any. + const type_safe::optional& scope() const noexcept + { + return scope_; + } + + /// \returns Whether or not the attribute is variadic. + bool is_variadic() const noexcept + { + return variadic_; + } + + /// \returns The arguments of the attribute, if they are any. + const type_safe::optional& arguments() const noexcept + { + return arguments_; + } + + private: + type_safe::optional scope_; + type_safe::optional arguments_; + std::string name_; + cpp_attribute_kind kind_ = cpp_attribute_kind::unknown; + bool variadic_; + }; + + /// A list of C++ attributes. + using cpp_attribute_list = std::vector; +} // namespace cppast + +#endif // CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED diff --git a/include/cppast/cpp_entity.hpp b/include/cppast/cpp_entity.hpp index 73f2bc7..177dc7e 100644 --- a/include/cppast/cpp_entity.hpp +++ b/include/cppast/cpp_entity.hpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace cppast @@ -123,6 +124,18 @@ namespace cppast 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)); + } + /// \returns The specified user data. void* user_data() const noexcept { @@ -162,6 +175,7 @@ namespace cppast std::string name_; std::string comment_; + cpp_attribute_list attributes_; type_safe::optional_ref parent_; mutable std::atomic user_data_; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e0ccd6..a381d17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ set(header ../include/cppast/compile_config.hpp ../include/cppast/cpp_alias_template.hpp ../include/cppast/cpp_array_type.hpp + ../include/cppast/cpp_attribute.hpp ../include/cppast/cpp_class.hpp ../include/cppast/cpp_class_template.hpp ../include/cppast/cpp_decltype_type.hpp