Update clang-format

This commit is contained in:
Jonathan Müller 2018-09-20 19:57:03 +02:00
commit 9f18b7f4d8
89 changed files with 11377 additions and 11546 deletions

View file

@ -2,10 +2,10 @@ AccessModifierOffset: -4
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: false AlignEscapedNewlinesLeft: Right
AlignOperands: true AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty AllowShortFunctionsOnASingleLine: Empty
@ -16,28 +16,50 @@ AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom
BreakBeforeBraces: Allman BraceWrapping:
BreakBeforeTernaryOperators: false AfterClass: true
BreakConstructorInitializersBeforeComma: false AfterControlStatement: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: All
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: false
ColumnLimit: 100
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0 ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
ColumnLimit: 100
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseLabels: false IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: true IndentWrappedFunctionNames: true
Language: Cpp
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: All NamespaceIndentation: Inner
PenaltyBreakBeforeFirstCallParameter: 19937 PenaltyBreakBeforeFirstCallParameter: 19937
PenaltyReturnTypeOnItsOwnLine: 19937 PenaltyReturnTypeOnItsOwnLine: 19937
PointerAlignment: Left PointerAlignment: Left
ReflowComments: false ReflowComments: true
SortIncludes: false SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false

View file

@ -5,7 +5,8 @@
/// \file /// \file
/// Generate equality comparisons. /// Generate equality comparisons.
/// ///
/// Given an input file, it will generate comparison operators for each class that has the [[generate::comparison]] attribute. /// Given an input file, it will generate comparison operators for each class that has the
/// [[generate::comparison]] attribute.
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
@ -94,8 +95,8 @@ void generate_comparison(const cppast::cpp_file& file)
{ {
// it is a new class // it is a new class
auto& class_ = static_cast<const cppast::cpp_class&>(e); auto& class_ = static_cast<const cppast::cpp_class&>(e);
auto& attribute = auto& attribute
cppast::has_attribute(e, "generate::comparison").value(); = cppast::has_attribute(e, "generate::comparison").value();
// generate requested operators // generate requested operators
if (attribute.arguments()) if (attribute.arguments())

View file

@ -5,8 +5,9 @@
/// \file /// \file
/// Generates enum category functions. /// Generates enum category functions.
/// ///
/// Given an input file, it will generate definitions for functions marked with [[generate::enum_category(name)]]. /// Given an input file, it will generate definitions for functions marked with
/// The function takes an enumerator and will return true if it is marked with the same category. /// [[generate::enum_category(name)]]. The function takes an enumerator and will return true if it
/// is marked with the same category.
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -24,8 +25,8 @@ bool is_category(const cppast::cpp_enum_value& e, const std::string& name)
if (auto attr = cppast::has_attribute(e, "generate::enum_category")) if (auto attr = cppast::has_attribute(e, "generate::enum_category"))
{ {
// ... by looking for the token // ... by looking for the token
auto iter = auto iter
std::find_if(attr.value().arguments().value().begin(), = std::find_if(attr.value().arguments().value().begin(),
attr.value().arguments().value().end(), attr.value().arguments().value().end(),
[&](const cppast::cpp_token& tok) { return tok.spelling == name; }); [&](const cppast::cpp_token& tok) { return tok.spelling == name; });
return iter != attr.value().arguments().value().end(); return iter != attr.value().arguments().value().end();
@ -42,8 +43,10 @@ const cppast::cpp_enum& get_enum(const cppast::cpp_entity_index& index,
// it is an enum // it is an enum
assert(param_type.kind() == cppast::cpp_type_kind::user_defined_t); assert(param_type.kind() == cppast::cpp_type_kind::user_defined_t);
// lookup definition // lookup definition
auto& definition = auto& definition = static_cast<const cppast::cpp_user_defined_type&>(param_type)
static_cast<const cppast::cpp_user_defined_type&>(param_type).entity().get(index)[0u].get(); .entity()
.get(index)[0u]
.get();
assert(definition.kind() == cppast::cpp_entity_kind::enum_t); assert(definition.kind() == cppast::cpp_entity_kind::enum_t);
return static_cast<const cppast::cpp_enum&>(definition); return static_cast<const cppast::cpp_enum&>(definition);

View file

@ -5,7 +5,8 @@
/// \file /// \file
/// Generates enum `to_string()` code. /// Generates enum `to_string()` code.
/// ///
/// Given an input file, it will generate a to_string() function for all enums marked with [[generate::to_string]]. /// Given an input file, it will generate a to_string() function for all enums marked with
/// [[generate::to_string]].
#include <iostream> #include <iostream>
@ -43,8 +44,8 @@ void generate_to_string(const cppast::cpp_file& file)
<< ":\n"; << ":\n";
// attribute can be used to override the string // attribute can be used to override the string
if (auto attr = if (auto attr
cppast::has_attribute(enumerator, "generate::to_string")) = cppast::has_attribute(enumerator, "generate::to_string"))
std::cout << " return " std::cout << " return "
<< attr.value().arguments().value().as_string() << attr.value().arguments().value().as_string()
<< ";\n"; << ";\n";

View file

@ -5,7 +5,8 @@
/// \file /// \file
/// Serialization code generation. /// Serialization code generation.
/// ///
/// Given an input file, it will generate a serialize() function for each class marked with [[generate::serialize]]. /// Given an input file, it will generate a serialize() function for each class marked with
/// [[generate::serialize]].
#include <iostream> #include <iostream>

View file

@ -7,22 +7,22 @@
#include <cstring> #include <cstring>
#include <type_safe/index.hpp>
#include <type_safe/flag_set.hpp> #include <type_safe/flag_set.hpp>
#include <type_safe/index.hpp>
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_ref.hpp> #include <cppast/cpp_entity_ref.hpp>
namespace cppast namespace cppast
{ {
enum cpp_access_specifier_kind : int; enum cpp_access_specifier_kind : int;
/// A simple string view implementation, like [std::string_view](). /// A simple string view implementation, like [std::string_view]().
/// ///
/// It "views" - stores a pointer to - some kind of string. /// It "views" - stores a pointer to - some kind of string.
class string_view class string_view
{ {
public: public:
/// \effects Creates it viewing the [std::string](). /// \effects Creates it viewing the [std::string]().
string_view(const std::string& str) noexcept : str_(str.c_str()), length_(str.length()) {} string_view(const std::string& str) noexcept : str_(str.c_str()), length_(str.length()) {}
@ -32,8 +32,7 @@ namespace cppast
/// \effects Creates it viewing the C string literal. /// \effects Creates it viewing the C string literal.
template <std::size_t Size> template <std::size_t Size>
constexpr string_view(const char (&str)[Size]) noexcept : str_(str), length_(Size - 1u) constexpr string_view(const char (&str)[Size]) noexcept : str_(str), length_(Size - 1u)
{ {}
}
/// \returns The number of characters. /// \returns The number of characters.
constexpr std::size_t length() const noexcept constexpr std::size_t length() const noexcept
@ -54,24 +53,22 @@ namespace cppast
return type_safe::at(str_, i); return type_safe::at(str_, i);
} }
private: private:
const char* str_; const char* str_;
std::size_t length_; std::size_t length_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
template <typename Tag> template <typename Tag>
class semantic_string_view class semantic_string_view
{ {
public: public:
template <typename T> template <typename T>
explicit semantic_string_view(T&& obj, explicit semantic_string_view(T&& obj, decltype(string_view(std::forward<T>(obj)), 0) = 0)
decltype(string_view(std::forward<T>(obj)), 0) = 0)
: str_(std::forward<T>(obj)) : str_(std::forward<T>(obj))
{ {}
}
const string_view& str() const noexcept const string_view& str() const noexcept
{ {
@ -81,51 +78,51 @@ namespace cppast
private: private:
string_view str_; string_view str_;
}; };
} // namespace detail } // namespace detail
/// A special [cppast::string_view]() representing a C++ keyword token. /// A special [cppast::string_view]() representing a C++ keyword token.
using keyword = detail::semantic_string_view<struct keyword_tag>; using keyword = detail::semantic_string_view<struct keyword_tag>;
/// A special [cppast::string_view]() representing a C++ identifier token. /// A special [cppast::string_view]() representing a C++ identifier token.
using identifier = detail::semantic_string_view<struct identifier_tag>; using identifier = detail::semantic_string_view<struct identifier_tag>;
/// A special [cppast::string_view]() representing a C++ string or character literal token. /// A special [cppast::string_view]() representing a C++ string or character literal token.
using string_literal = detail::semantic_string_view<struct str_literal_tag>; using string_literal = detail::semantic_string_view<struct str_literal_tag>;
/// A special [cppast::string_view]() representing a C++ integer literal token. /// A special [cppast::string_view]() representing a C++ integer literal token.
using int_literal = detail::semantic_string_view<struct int_literal_tag>; using int_literal = detail::semantic_string_view<struct int_literal_tag>;
/// A special [cppast::string_view]() representing a C++ floating point literal token. /// A special [cppast::string_view]() representing a C++ floating point literal token.
using float_literal = detail::semantic_string_view<struct float_literal_tag>; using float_literal = detail::semantic_string_view<struct float_literal_tag>;
/// A special [cppast::string_view]() representing a C++ punctuation token like `.` or `(`. /// A special [cppast::string_view]() representing a C++ punctuation token like `.` or `(`.
using punctuation = detail::semantic_string_view<struct punctuation_tag>; using punctuation = detail::semantic_string_view<struct punctuation_tag>;
/// A special [cppast::string_view]() representing a C++ preprocessor token. /// A special [cppast::string_view]() representing a C++ preprocessor token.
using preprocessor_token = detail::semantic_string_view<struct preprocessor_tag>; using preprocessor_token = detail::semantic_string_view<struct preprocessor_tag>;
/// A special [cppast::string_view]() representing a comment. /// A special [cppast::string_view]() representing a comment.
using comment = detail::semantic_string_view<struct comment_tag>; using comment = detail::semantic_string_view<struct comment_tag>;
/// A special [cppast::string_view]() representing a sequence of unknown C++ tokens. /// A special [cppast::string_view]() representing a sequence of unknown C++ tokens.
using token_seq = detail::semantic_string_view<struct token_seq_tag>; using token_seq = detail::semantic_string_view<struct token_seq_tag>;
/// Tag type to represent an end-of-line character. /// Tag type to represent an end-of-line character.
const struct newl_t const struct newl_t
{ {
} newl{}; } newl{};
/// Tag type to represent a single space character. /// Tag type to represent a single space character.
const struct whitespace_t const struct whitespace_t
{ {
} whitespace{}; } whitespace{};
/// Flags that control the code formatting. /// Flags that control the code formatting.
/// ///
/// If a flag is set, it adds additional whitespace. /// If a flag is set, it adds additional whitespace.
/// If no flags are set, it will only add the whitespace necessary to separate tokens. /// If no flags are set, it will only add the whitespace necessary to separate tokens.
enum class formatting_flags enum class formatting_flags
{ {
brace_nl, //< Set to put the opening braces on a new line. brace_nl, //< Set to put the opening braces on a new line.
brace_ws, //< Set to put the opening brace at the end of the line after whitespace. brace_ws, //< Set to put the opening brace at the end of the line after whitespace.
@ -136,18 +133,18 @@ namespace cppast
operator_ws, //< Set to put whitespace around operators. operator_ws, //< Set to put whitespace around operators.
_flag_set_size, //< \exclude _flag_set_size, //< \exclude
}; };
/// A set of formatting flags. /// A set of formatting flags.
using formatting = type_safe::flag_set<formatting_flags>; using formatting = type_safe::flag_set<formatting_flags>;
/// Base class to control the code generation. /// Base class to control the code generation.
/// ///
/// Inherit from it to customize how a [cppast::cpp_entity]() is printed /// Inherit from it to customize how a [cppast::cpp_entity]() is printed
/// by [cppast::generate_code](). /// by [cppast::generate_code]().
class code_generator class code_generator
{ {
public: public:
code_generator(const code_generator&) = delete; code_generator(const code_generator&) = delete;
code_generator& operator=(const code_generator&) = delete; code_generator& operator=(const code_generator&) = delete;
@ -194,7 +191,8 @@ namespace cppast
output& operator=(const output&) = delete; output& operator=(const output&) = delete;
/// \returns Whether or not the `on_XXX` function returned something other than `exclude` or `custom`. /// \returns Whether or not the `on_XXX` function returned something other than `exclude` or
/// `custom`.
explicit operator bool() const noexcept explicit operator bool() const noexcept
{ {
return !options_.is_set(exclude) && !options_.is_set(custom); return !options_.is_set(exclude) && !options_.is_set(custom);
@ -236,7 +234,8 @@ namespace cppast
gen_->on_container_end(*this, *e_); gen_->on_container_end(*this, *e_);
} }
/// \effects Call `do_indent()` followed by `do_write_newline()` (if `print_newline` is `true`). /// \effects Call `do_indent()` followed by `do_write_newline()` (if `print_newline` is
/// `true`).
void indent(bool print_newline = true) const noexcept void indent(bool print_newline = true) const noexcept
{ {
gen_->do_indent(); gen_->do_indent();
@ -362,7 +361,7 @@ namespace cppast
mutable bool was_excluded_ = false; mutable bool was_excluded_ = false;
}; };
protected: protected:
code_generator() noexcept = default; code_generator() noexcept = default;
/// \returns The entity whose code is being generated with [cppast::generate_code()](). /// \returns The entity whose code is being generated with [cppast::generate_code()]().
@ -374,10 +373,11 @@ namespace cppast
/// \effects Generates the code for the specified entity. /// \effects Generates the code for the specified entity.
/// It can be used to generate additional entities while generating another one. /// It can be used to generate additional entities while generating another one.
/// \returns Whether or not any code was generated. /// \returns Whether or not any code was generated.
/// \notes This does not affect the main entity, but otherwise behaves just like [cppast::generate_code()](). /// \notes This does not affect the main entity, but otherwise behaves just like
/// [cppast::generate_code()]().
bool generate_code(const cpp_entity& entity); bool generate_code(const cpp_entity& entity);
private: private:
/// \returns The formatting options that should be used. /// \returns The formatting options that should be used.
/// The base class version has no flags set. /// The base class version has no flags set.
virtual formatting do_get_formatting() const virtual formatting do_get_formatting() const
@ -426,7 +426,8 @@ namespace cppast
virtual void do_indent() = 0; virtual void do_indent() = 0;
/// \effects Will be invoked when the indentation level should be decreased by one. /// \effects Will be invoked when the indentation level should be decreased by one.
/// The level change must be applied immediately if nothing else has been written on the current line. /// The level change must be applied immediately if nothing else has been written on the current
/// line.
virtual void do_unindent() = 0; virtual void do_unindent() = 0;
/// \effects Writes the given token sequence. /// \effects Writes the given token sequence.
@ -447,8 +448,7 @@ namespace cppast
do_write_token_seq(identifier); do_write_token_seq(identifier);
} }
/// \group write /// \group write
virtual bool do_write_reference(type_safe::array_ref<const cpp_entity_id> id, virtual bool do_write_reference(type_safe::array_ref<const cpp_entity_id> id, string_view name)
string_view name)
{ {
(void)id; (void)id;
do_write_token_seq(name); do_write_token_seq(name);
@ -512,30 +512,30 @@ namespace cppast
type_safe::optional_ref<const cpp_entity> main_entity_; type_safe::optional_ref<const cpp_entity> main_entity_;
friend bool generate_code(code_generator& generator, const cpp_entity& e); friend bool generate_code(code_generator& generator, const cpp_entity& e);
}; };
/// Generates code for the given entity. /// Generates code for the given entity.
/// ///
/// How the code is generated is customized by the generator. /// How the code is generated is customized by the generator.
/// ///
/// \returns Whether or not any code was actually written. /// \returns Whether or not any code was actually written.
bool generate_code(code_generator& generator, const cpp_entity& e); bool generate_code(code_generator& generator, const cpp_entity& e);
/// \exclude /// \exclude
class cpp_template_argument; class cpp_template_argument;
/// \exclude /// \exclude
class cpp_token_string; class cpp_token_string;
/// \exclude /// \exclude
namespace detail namespace detail
{ {
void write_template_arguments( void write_template_arguments(
code_generator::output& output, code_generator::output& output,
type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments); type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments);
void write_token_string(code_generator::output& output, const cpp_token_string& tokens); void write_token_string(code_generator::output& output, const cpp_token_string& tokens);
} // namespace detail } // namespace detail
} // namespace cppast } // namespace cppast
#endif // CPPAST_CODE_GENERATOR_HPP_INCLUDED #endif // CPPAST_CODE_GENERATOR_HPP_INCLUDED

View file

@ -8,16 +8,16 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <type_safe/reference.hpp>
#include <type_safe/flag_set.hpp> #include <type_safe/flag_set.hpp>
#include <type_safe/reference.hpp>
#include <cppast/detail/assert.hpp> #include <cppast/detail/assert.hpp>
namespace cppast namespace cppast
{ {
/// The C++ standard that should be used. /// The C++ standard that should be used.
enum class cpp_standard enum class cpp_standard
{ {
cpp_98, cpp_98,
cpp_03, cpp_03,
cpp_11, cpp_11,
@ -26,12 +26,12 @@ namespace cppast
cpp_1z, //< Upcoming C++17 (experimental). cpp_1z, //< Upcoming C++17 (experimental).
cpp_latest = cpp_standard::cpp_14, //< The latest supported C++ standard. cpp_latest = cpp_standard::cpp_14, //< The latest supported C++ standard.
}; };
/// \returns A human readable string representing the option, /// \returns A human readable string representing the option,
/// it is e.g. `c++14` for `cpp_14`. /// it is e.g. `c++14` for `cpp_14`.
inline const char* to_string(cpp_standard standard) noexcept inline const char* to_string(cpp_standard standard) noexcept
{ {
switch (standard) switch (standard)
{ {
case cpp_standard::cpp_98: case cpp_standard::cpp_98:
@ -48,26 +48,26 @@ namespace cppast
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return "ups"; return "ups";
} }
/// Other special compilation flags. /// Other special compilation flags.
enum class compile_flag enum class compile_flag
{ {
gnu_extensions, //< Enable GCC extensions. gnu_extensions, //< Enable GCC extensions.
ms_extensions, //< Enable MSVC extensions. ms_extensions, //< Enable MSVC extensions.
ms_compatibility, //< Enable MSVC compatibility. ms_compatibility, //< Enable MSVC compatibility.
_flag_set_size, //< \exclude _flag_set_size, //< \exclude
}; };
/// A [ts::flag_set]() of [cppast::compile_flag](). /// A [ts::flag_set]() of [cppast::compile_flag]().
using compile_flags = type_safe::flag_set<compile_flag>; using compile_flags = type_safe::flag_set<compile_flag>;
/// Base class for the configuration of a [cppast::parser](). /// Base class for the configuration of a [cppast::parser]().
class compile_config class compile_config
{ {
public: public:
/// \effects Sets the given C++ standard and compilation flags. /// \effects Sets the given C++ standard and compilation flags.
void set_flags(cpp_standard standard, compile_flags flags = {}) void set_flags(cpp_standard standard, compile_flags flags = {})
{ {
@ -99,7 +99,7 @@ namespace cppast
return do_get_name(); return do_get_name();
} }
protected: protected:
compile_config(std::vector<std::string> def_flags) : flags_(std::move(def_flags)) {} compile_config(std::vector<std::string> def_flags) : flags_(std::move(def_flags)) {}
compile_config(const compile_config&) = default; compile_config(const compile_config&) = default;
@ -117,7 +117,7 @@ namespace cppast
return flags_; return flags_;
} }
private: private:
/// \effects Sets the given C++ standard and compilation flags. /// \effects Sets the given C++ standard and compilation flags.
virtual void do_set_flags(cpp_standard standard, compile_flags flags) = 0; virtual void do_set_flags(cpp_standard standard, compile_flags flags) = 0;
@ -135,7 +135,7 @@ namespace cppast
virtual const char* do_get_name() const noexcept = 0; virtual const char* do_get_name() const noexcept = 0;
std::vector<std::string> flags_; std::vector<std::string> flags_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_COMPILE_CONFIG_HPP_INCLUDED #endif // CPPAST_COMPILE_CONFIG_HPP_INCLUDED

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a C++ alias template. /// A [cppast::cpp_entity]() modelling a C++ alias template.
class cpp_alias_template final : public cpp_template class cpp_alias_template final : public cpp_template
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_alias_template](). /// Builder for [cppast::cpp_alias_template]().
@ -29,16 +29,15 @@ namespace cppast
return static_cast<const cpp_type_alias&>(*begin()); return static_cast<const cpp_type_alias&>(*begin());
} }
private: private:
cpp_alias_template(std::unique_ptr<cpp_type_alias> alias) cpp_alias_template(std::unique_ptr<cpp_type_alias> alias)
: cpp_template(std::unique_ptr<cpp_entity>(alias.release())) : cpp_template(std::unique_ptr<cpp_entity>(alias.release()))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_builder<cpp_alias_template, cpp_type_alias>; friend basic_builder<cpp_alias_template, cpp_type_alias>;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED #endif // CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// An array of a [cppast::cpp_type](). /// An array of a [cppast::cpp_type]().
class cpp_array_type final : public cpp_type class cpp_array_type final : public cpp_type
{ {
public: public:
/// \returns A newly created array. /// \returns A newly created array.
/// \notes `size` may be `nullptr`. /// \notes `size` may be `nullptr`.
static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type, static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type,
@ -29,18 +29,17 @@ namespace cppast
return *type_; return *type_;
} }
/// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the array. /// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the
/// \notes An unsized array - `T[]` - does not have a size. /// array. \notes An unsized array - `T[]` - does not have a size.
type_safe::optional_ref<const cpp_expression> size() const noexcept type_safe::optional_ref<const cpp_expression> size() const noexcept
{ {
return type_safe::opt_cref(size_.get()); return type_safe::opt_cref(size_.get());
} }
private: private:
cpp_array_type(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> size) cpp_array_type(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> size)
: type_(std::move(type)), size_(std::move(size)) : type_(std::move(type)), size_(std::move(size))
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -49,7 +48,7 @@ namespace cppast
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
std::unique_ptr<cpp_expression> size_; std::unique_ptr<cpp_expression> size_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED #endif // CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED

View file

@ -15,9 +15,9 @@
namespace cppast namespace cppast
{ {
/// The known C++ attributes. /// The known C++ attributes.
enum class cpp_attribute_kind enum class cpp_attribute_kind
{ {
// update get_attribute_kind() in tokenizer, when updating this // update get_attribute_kind() in tokenizer, when updating this
alignas_, alignas_,
@ -29,32 +29,30 @@ namespace cppast
noreturn, noreturn,
unknown, //< An unknown attribute. unknown, //< An unknown attribute.
}; };
/// A C++ attribute, including `alignas` specifiers. /// A C++ attribute, including `alignas` specifiers.
/// ///
/// It consists of a name, an optional namespace scope and optional arguments. /// 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 scope is just a single identifier and doesn't include the `::` and can be given explicitly
/// The arguments are as specified in the source code but do not include the outer-most `(` and `)`. /// or via using. The arguments are as specified in the source code but do not include the
/// It can also be variadic or not. /// outer-most `(` and `)`. It can also be variadic or not.
/// ///
/// An attribute can be known or unknown. /// An attribute can be known or unknown.
/// A known attribute will have the [cppast::cpp_attribute_kind]() set properly. /// A known attribute will have the [cppast::cpp_attribute_kind]() set properly.
class cpp_attribute class cpp_attribute
{ {
public: public:
/// \effects Creates a known attribute, potentially with arguments. /// \effects Creates a known attribute, potentially with arguments.
cpp_attribute(cpp_attribute_kind kind, type_safe::optional<cpp_token_string> 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. /// \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, cpp_attribute(type_safe::optional<std::string> scope, std::string name,
type_safe::optional<cpp_token_string> arguments, bool is_variadic) type_safe::optional<cpp_token_string> arguments, bool is_variadic)
: scope_(std::move(scope)), : scope_(std::move(scope)), arguments_(std::move(arguments)), name_(std::move(name)),
arguments_(std::move(arguments)),
name_(std::move(name)),
variadic_(is_variadic) variadic_(is_variadic)
{ {}
}
/// \returns The kind of attribute, if it is known. /// \returns The kind of attribute, if it is known.
const cpp_attribute_kind& kind() const noexcept const cpp_attribute_kind& kind() const noexcept
@ -86,37 +84,37 @@ namespace cppast
return arguments_; return arguments_;
} }
private: private:
type_safe::optional<std::string> scope_; type_safe::optional<std::string> scope_;
type_safe::optional<cpp_token_string> arguments_; type_safe::optional<cpp_token_string> arguments_;
std::string name_; std::string name_;
cpp_attribute_kind kind_ = cpp_attribute_kind::unknown; cpp_attribute_kind kind_ = cpp_attribute_kind::unknown;
bool variadic_; bool variadic_;
}; };
/// A list of C++ attributes. /// A list of C++ attributes.
using cpp_attribute_list = std::vector<cpp_attribute>; using cpp_attribute_list = std::vector<cpp_attribute>;
/// Checks whether an attribute is given. /// Checks whether an attribute is given.
/// \returns `true` if the given attribute list (1-2) / entity (3-4) contain /// \returns `true` if the given attribute list (1-2) / entity (3-4) contain
/// an attribute of the given name (1+3) / kind (2+4). /// an attribute of the given name (1+3) / kind (2+4).
/// `false` otherwise. /// `false` otherwise.
/// \group has_attribute /// \group has_attribute
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes, type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
const std::string& name); const std::string& name);
/// \group has_attribute /// \group has_attribute
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes, type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_attribute_list& attributes,
cpp_attribute_kind kind); cpp_attribute_kind kind);
class cpp_entity; class cpp_entity;
/// \group has_attribute /// \group has_attribute
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e, type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
const std::string& name); const std::string& name);
/// \group has_attribute /// \group has_attribute
type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e, type_safe::optional_ref<const cpp_attribute> has_attribute(const cpp_entity& e,
cpp_attribute_kind kind); cpp_attribute_kind kind);
} // namespace cppast } // namespace cppast

View file

@ -12,32 +12,32 @@
namespace cppast namespace cppast
{ {
/// The keyword used on the declaration of a [cppast::cpp_class](). /// The keyword used on the declaration of a [cppast::cpp_class]().
enum class cpp_class_kind enum class cpp_class_kind
{ {
class_t, class_t,
struct_t, struct_t,
union_t, union_t,
}; };
/// \returns The keyword as a string. /// \returns The keyword as a string.
const char* to_string(cpp_class_kind kind) noexcept; const char* to_string(cpp_class_kind kind) noexcept;
/// The C++ access specifiers. /// The C++ access specifiers.
enum cpp_access_specifier_kind : int enum cpp_access_specifier_kind : int
{ {
cpp_public, cpp_public,
cpp_protected, cpp_protected,
cpp_private cpp_private
}; };
/// \returns The access specifier keyword as a string. /// \returns The access specifier keyword as a string.
const char* to_string(cpp_access_specifier_kind access) noexcept; const char* to_string(cpp_access_specifier_kind access) noexcept;
/// A [cppast::cpp_entity]() modelling a C++ access specifier. /// A [cppast::cpp_entity]() modelling a C++ access specifier.
class cpp_access_specifier final : public cpp_entity class cpp_access_specifier final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created access specifier. /// \returns A newly created access specifier.
@ -54,30 +54,27 @@ namespace cppast
return access_; return access_;
} }
private: private:
cpp_access_specifier(cpp_access_specifier_kind access) cpp_access_specifier(cpp_access_specifier_kind access)
: cpp_entity(to_string(access)), access_(access) : cpp_entity(to_string(access)), access_(access)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_access_specifier_kind access_; cpp_access_specifier_kind access_;
}; };
/// A [cppast::cpp_entity]() modelling a base class specifier. /// A [cppast::cpp_entity]() modelling a base class specifier.
class cpp_base_class final : public cpp_entity class cpp_base_class final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created base class specifier. /// \returns A newly created base class specifier.
/// \notes It is not meant to be registered at the [cppast::cpp_entity_index](), /// \notes It is not meant to be registered at the [cppast::cpp_entity_index](),
/// as nothing can refer to the specifier itself. /// as nothing can refer to the specifier itself.
static std::unique_ptr<cpp_base_class> build(std::string name, static std::unique_ptr<cpp_base_class> build(std::string name, std::unique_ptr<cpp_type> base,
std::unique_ptr<cpp_type> base, cpp_access_specifier_kind access, bool is_virtual)
cpp_access_specifier_kind access,
bool is_virtual)
{ {
return std::unique_ptr<cpp_base_class>( return std::unique_ptr<cpp_base_class>(
new cpp_base_class(std::move(name), std::move(base), access, is_virtual)); new cpp_base_class(std::move(name), std::move(base), access, is_virtual));
@ -101,30 +98,29 @@ namespace cppast
return virtual_; return virtual_;
} }
private: private:
cpp_base_class(std::string name, std::unique_ptr<cpp_type> base, cpp_base_class(std::string name, std::unique_ptr<cpp_type> base,
cpp_access_specifier_kind access, bool is_virtual) cpp_access_specifier_kind access, bool is_virtual)
: cpp_entity(std::move(name)), type_(std::move(base)), access_(access), virtual_(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; cpp_entity_kind do_get_entity_kind() const noexcept override;
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
cpp_access_specifier_kind access_; cpp_access_specifier_kind access_;
bool virtual_; bool virtual_;
}; };
/// A [cppast::cpp_entity]() modelling a C++ class. /// A [cppast::cpp_entity]() modelling a C++ class.
/// ///
/// This can either be a definition or just a forward declaration. /// This can either be a definition or just a forward declaration.
/// If it is just a forward declaration, /// If it is just a forward declaration,
/// everything except the class type will not be available. /// everything except the class type will not be available.
class cpp_class final : public cpp_entity, class cpp_class final : public cpp_entity,
public cpp_entity_container<cpp_class, cpp_entity>, public cpp_entity_container<cpp_class, cpp_entity>,
public cpp_forward_declarable public cpp_forward_declarable
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_class](). /// Builds a [cppast::cpp_class]().
@ -134,8 +130,7 @@ namespace cppast
/// \effects Sets the name and kind and whether it is `final`. /// \effects Sets the name and kind and whether it is `final`.
explicit builder(std::string name, cpp_class_kind kind, bool is_final = false) explicit builder(std::string name, cpp_class_kind kind, bool is_final = false)
: class_(new cpp_class(std::move(name), kind, is_final)) : class_(new cpp_class(std::move(name), kind, is_final))
{ {}
}
/// \effects Marks the class as final. /// \effects Marks the class as final.
void is_final() noexcept void is_final() noexcept
@ -192,8 +187,8 @@ namespace cppast
/// \notes This is intended for templated classes only. /// \notes This is intended for templated classes only.
std::unique_ptr<cpp_class> finish(type_safe::optional<cpp_entity_ref> semantic_parent); 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. /// \effects Returns the finish class without registering it and marks it as forward
/// \notes This is intended for templated classes only. /// declaration. \notes This is intended for templated classes only.
std::unique_ptr<cpp_class> finish_declaration(cpp_entity_id definition_id); std::unique_ptr<cpp_class> finish_declaration(cpp_entity_id definition_id);
private: private:
@ -218,11 +213,10 @@ namespace cppast
return type_safe::ref(bases_); return type_safe::ref(bases_);
} }
private: private:
cpp_class(std::string name, cpp_class_kind kind, bool final) cpp_class(std::string name, cpp_class_kind kind, bool final)
: cpp_entity(std::move(name)), kind_(kind), final_(final) : cpp_entity(std::move(name)), kind_(kind), final_(final)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
@ -234,16 +228,16 @@ namespace cppast
detail::intrusive_list<cpp_base_class> bases_; detail::intrusive_list<cpp_base_class> bases_;
cpp_class_kind kind_; cpp_class_kind kind_;
bool final_; bool final_;
}; };
/// \returns The type the base class refers to. /// \returns The type the base class refers to.
/// It is either a class or some form of typedef. /// 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, type_safe::optional_ref<const cpp_entity> get_class_or_typedef(const cpp_entity_index& index,
const cpp_base_class& base); const cpp_base_class& base);
/// \returns The type the base class refers to. /// \returns The type the base class refers to.
/// Typedefs are unwrapped. /// Typedefs are unwrapped.
type_safe::optional_ref<const cpp_class> get_class(const cpp_entity_index& index, type_safe::optional_ref<const cpp_class> get_class(const cpp_entity_index& index,
const cpp_base_class& base); const cpp_base_class& base);
} // namespace cppast } // namespace cppast

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a class template. /// A [cppast::cpp_entity]() modelling a class template.
class cpp_class_template final : public cpp_template class cpp_class_template final : public cpp_template
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_class_template](). /// Builder for [cppast::cpp_class_template]().
@ -29,21 +29,20 @@ namespace cppast
return static_cast<const cpp_class&>(*begin()); return static_cast<const cpp_class&>(*begin());
} }
private: private:
cpp_class_template(std::unique_ptr<cpp_class> func) cpp_class_template(std::unique_ptr<cpp_class> func)
: cpp_template(std::unique_ptr<cpp_entity>(func.release())) : cpp_template(std::unique_ptr<cpp_entity>(func.release()))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_builder<cpp_class_template, cpp_class>; friend basic_builder<cpp_class_template, cpp_class>;
}; };
/// A [cppast::cpp_entity]() modelling a class template specialization. /// A [cppast::cpp_entity]() modelling a class template specialization.
class cpp_class_template_specialization final : public cpp_template_specialization class cpp_class_template_specialization final : public cpp_template_specialization
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_class_template_specialization](). /// Builder for [cppast::cpp_class_template_specialization]().
@ -59,16 +58,15 @@ namespace cppast
return static_cast<const cpp_class&>(*begin()); return static_cast<const cpp_class&>(*begin());
} }
private: private:
cpp_class_template_specialization(std::unique_ptr<cpp_class> func, cpp_template_ref primary) 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_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend specialization_builder<cpp_class_template_specialization, cpp_class>; friend specialization_builder<cpp_class_template_specialization, cpp_class>;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED #endif // CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_type]() that isn't given but taken from an expression. /// A [cppast::cpp_type]() that isn't given but taken from an expression.
class cpp_decltype_type final : public cpp_type class cpp_decltype_type final : public cpp_type
{ {
public: public:
/// \returns A newly created `decltype` type. /// \returns A newly created `decltype` type.
static std::unique_ptr<cpp_decltype_type> build(std::unique_ptr<cpp_expression> expr) static std::unique_ptr<cpp_decltype_type> build(std::unique_ptr<cpp_expression> expr)
{ {
@ -26,7 +26,7 @@ namespace cppast
return *expr_; return *expr_;
} }
private: private:
cpp_decltype_type(std::unique_ptr<cpp_expression> expr) : expr_(std::move(expr)) {} cpp_decltype_type(std::unique_ptr<cpp_expression> expr) : expr_(std::move(expr)) {}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
@ -35,26 +35,26 @@ namespace cppast
} }
std::unique_ptr<cpp_expression> expr_; std::unique_ptr<cpp_expression> expr_;
}; };
/// A [cppast::cpp_type]() that isn't given but deduced using the `decltype` rules. /// A [cppast::cpp_type]() that isn't given but deduced using the `decltype` rules.
class cpp_decltype_auto_type final : public cpp_type class cpp_decltype_auto_type final : public cpp_type
{ {
public: public:
/// \returns A newly created `auto` type. /// \returns A newly created `auto` type.
static std::unique_ptr<cpp_decltype_auto_type> build() static std::unique_ptr<cpp_decltype_auto_type> build()
{ {
return std::unique_ptr<cpp_decltype_auto_type>(new cpp_decltype_auto_type); return std::unique_ptr<cpp_decltype_auto_type>(new cpp_decltype_auto_type);
} }
private: private:
cpp_decltype_auto_type() = default; cpp_decltype_auto_type() = default;
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
return cpp_type_kind::decltype_auto_t; return cpp_type_kind::decltype_auto_t;
} }
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED #endif // CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED

View file

@ -10,25 +10,25 @@
#include <type_safe/optional_ref.hpp> #include <type_safe/optional_ref.hpp>
#include <cppast/detail/intrusive_list.hpp>
#include <cppast/cpp_attribute.hpp> #include <cppast/cpp_attribute.hpp>
#include <cppast/cpp_token.hpp> #include <cppast/cpp_token.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast namespace cppast
{ {
class cpp_entity; class cpp_entity;
enum class cpp_entity_kind; enum class cpp_entity_kind;
class cpp_entity_index; class cpp_entity_index;
struct cpp_entity_id; struct cpp_entity_id;
class cpp_template_parameter; class cpp_template_parameter;
class cpp_template; class cpp_template;
/// The name of a scope. /// The name of a scope.
/// ///
/// It is a combination of a name and optional template parameters. /// It is a combination of a name and optional template parameters.
class cpp_scope_name class cpp_scope_name
{ {
public: public:
/// \effects Creates a scope out of a given entity. /// \effects Creates a scope out of a given entity.
cpp_scope_name(type_safe::object_ref<const cpp_entity> entity); cpp_scope_name(type_safe::object_ref<const cpp_entity> entity);
@ -41,20 +41,19 @@ namespace cppast
return templ_.has_value(); return templ_.has_value();
} }
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities of the scope. /// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities
/// \requires The scope is templated. /// of the scope. \requires The scope is templated.
detail::iteratable_intrusive_list<cpp_template_parameter> template_parameters() const detail::iteratable_intrusive_list<cpp_template_parameter> template_parameters() const noexcept;
noexcept;
private: private:
type_safe::object_ref<const cpp_entity> entity_; type_safe::object_ref<const cpp_entity> entity_;
type_safe::optional_ref<const cpp_template> templ_; type_safe::optional_ref<const cpp_template> templ_;
}; };
/// The base class for all entities in the C++ AST. /// The base class for all entities in the C++ AST.
class cpp_entity : detail::intrusive_list_node<cpp_entity> class cpp_entity : detail::intrusive_list_node<cpp_entity>
{ {
public: public:
cpp_entity(const cpp_entity&) = delete; cpp_entity(const cpp_entity&) = delete;
cpp_entity& operator=(const cpp_entity&) = delete; cpp_entity& operator=(const cpp_entity&) = delete;
@ -89,12 +88,11 @@ namespace cppast
/// \returns The documentation comment associated with that entity, if any. /// \returns The documentation comment associated with that entity, if any.
/// \notes A documentation comment can have three forms: /// \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. `/**`. /// * 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. /// `/**`. One space after the leading sequence will be skipped. It ends either with `*/` or
/// It ends either with `*/` or `**/`. /// `**/`. After a newline all whitespace is skipped, as well as an optional `*` followed by
/// After a newline all whitespace is skipped, as well as an optional `*` followed by another optional space, /// another optional space, as well as trailing whitespace on each line. I.e. `/** a\n * b
/// as well as trailing whitespace on each line. /// */` yields the text `a\nb`.
/// 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 '!`, /// * A C++ style doc comment. It is a C++ style comment starting with an additional `/` or '!`,
/// i.e. `///` or `//!`. /// i.e. `///` or `//!`.
/// One space character after the leading sequence will be skipped, /// One space character after the leading sequence will be skipped,
@ -153,17 +151,18 @@ namespace cppast
/// User data is just some kind of pointer, there are no requirements. /// User data is just some kind of pointer, there are no requirements.
/// The class will do no lifetime management. /// 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. /// 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 void set_user_data(void* data) const noexcept
{ {
user_data_ = data; user_data_ = data;
} }
protected: protected:
/// \effects Creates it giving it the the name. /// \effects Creates it giving it the the name.
cpp_entity(std::string name) : name_(std::move(name)), user_data_(nullptr) {} cpp_entity(std::string name) : name_(std::move(name)), user_data_(nullptr) {}
private: private:
/// \returns The kind of the entity. /// \returns The kind of the entity.
virtual cpp_entity_kind do_get_entity_kind() const noexcept = 0; virtual cpp_entity_kind do_get_entity_kind() const noexcept = 0;
@ -188,14 +187,14 @@ namespace cppast
template <typename T> template <typename T>
friend struct detail::intrusive_list_access; friend struct detail::intrusive_list_access;
friend detail::intrusive_list_node<cpp_entity>; friend detail::intrusive_list_node<cpp_entity>;
}; };
/// A [cppast::cpp_entity]() that isn't exposed directly. /// A [cppast::cpp_entity]() that isn't exposed directly.
/// ///
/// The only information available is the raw source code. /// The only information available is the raw source code.
class cpp_unexposed_entity final : public cpp_entity class cpp_unexposed_entity final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly built and registered unexposed entity. /// \returns A newly built and registered unexposed entity.
@ -213,26 +212,25 @@ namespace cppast
return spelling_; return spelling_;
} }
private: private:
cpp_unexposed_entity(std::string name, cpp_token_string spelling) cpp_unexposed_entity(std::string name, cpp_token_string spelling)
: cpp_entity(std::move(name)), spelling_(std::move(spelling)) : cpp_entity(std::move(name)), spelling_(std::move(spelling))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_token_string spelling_; cpp_token_string spelling_;
}; };
/// \returns Whether or not the entity is templated. /// \returns Whether or not the entity is templated.
/// If this function returns `true` that means the entity is not the "real" entity, /// 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. /// 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. /// \notes Do not use this entity other to read information from the template entity.
bool is_templated(const cpp_entity& e) noexcept; bool is_templated(const cpp_entity& e) noexcept;
/// \returns Whether or not the given entity is "friended", /// \returns Whether or not the given entity is "friended",
/// that is, its declaration exists as part of a [cppast::cpp_friend]() declaration. /// that is, its declaration exists as part of a [cppast::cpp_friend]() declaration.
bool is_friended(const cpp_entity& e) noexcept; bool is_friended(const cpp_entity& e) noexcept;
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENTITY_HPP_INCLUDED #endif // CPPAST_CPP_ENTITY_HPP_INCLUDED

View file

@ -9,13 +9,13 @@
namespace cppast namespace cppast
{ {
/// Helper class for entities that are containers. /// Helper class for entities that are containers.
/// ///
/// Inherit from it to generate container access. /// Inherit from it to generate container access.
template <class Derived, typename T> template <class Derived, typename T>
class cpp_entity_container class cpp_entity_container
{ {
public: public:
using iterator = typename detail::intrusive_list<T>::const_iterator; using iterator = typename detail::intrusive_list<T>::const_iterator;
/// \returns A const iterator to the first child. /// \returns A const iterator to the first child.
@ -30,7 +30,7 @@ namespace cppast
return children_.end(); return children_.end();
} }
protected: protected:
/// \effects Adds a new child to the container. /// \effects Adds a new child to the container.
void add_child(std::unique_ptr<T> ptr) noexcept void add_child(std::unique_ptr<T> ptr) noexcept
{ {
@ -51,9 +51,9 @@ namespace cppast
~cpp_entity_container() noexcept = default; ~cpp_entity_container() noexcept = default;
private: private:
detail::intrusive_list<T> children_; detail::intrusive_list<T> children_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED #endif // CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED

View file

@ -16,13 +16,13 @@
namespace cppast namespace cppast
{ {
class cpp_entity; class cpp_entity;
class cpp_file; class cpp_file;
class cpp_namespace; class cpp_namespace;
/// \exclude /// \exclude
namespace detail namespace detail
{ {
constexpr std::size_t fnv_basis = 14695981039346656037ull; constexpr std::size_t fnv_basis = 14695981039346656037ull;
constexpr std::size_t fnv_prime = 1099511628211ull; constexpr std::size_t fnv_prime = 1099511628211ull;
@ -31,34 +31,34 @@ namespace cppast
{ {
return *str ? id_hash(str + 1, (hash ^ std::size_t(*str)) * fnv_prime) : hash; return *str ? id_hash(str + 1, (hash ^ std::size_t(*str)) * fnv_prime) : hash;
} }
} // namespace detail } // namespace detail
/// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity](). /// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity]().
/// ///
/// It is comparable for equality. /// It is comparable for equality.
struct cpp_entity_id : type_safe::strong_typedef<cpp_entity_id, std::size_t>, struct cpp_entity_id : type_safe::strong_typedef<cpp_entity_id, std::size_t>,
type_safe::strong_typedef_op::equality_comparison<cpp_entity_id> 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 std::string& str) : cpp_entity_id(str.c_str()) {}
explicit cpp_entity_id(const char* str) : strong_typedef(detail::id_hash(str)) {} explicit cpp_entity_id(const char* str) : strong_typedef(detail::id_hash(str)) {}
}; };
inline namespace literals inline namespace literals
{ {
/// \returns A new [cppast::cpp_entity_id]() created from the given string. /// \returns A new [cppast::cpp_entity_id]() created from the given string.
inline cpp_entity_id operator"" _id(const char* str, std::size_t) inline cpp_entity_id operator"" _id(const char* str, std::size_t)
{ {
return cpp_entity_id(str); return cpp_entity_id(str);
} }
} } // namespace literals
/// An index of all [cppast::cpp_entity]() objects created. /// An index of all [cppast::cpp_entity]() objects created.
/// ///
/// It maps [cppast::cpp_entity_id]() to references to the [cppast::cpp_entity]() objects. /// It maps [cppast::cpp_entity_id]() to references to the [cppast::cpp_entity]() objects.
class cpp_entity_index class cpp_entity_index
{ {
public: public:
/// Exception thrown on duplicate entity definition. /// Exception thrown on duplicate entity definition.
class duplicate_definition_error : public std::logic_error class duplicate_definition_error : public std::logic_error
{ {
@ -93,28 +93,27 @@ namespace cppast
/// \effects Registers a new [cppast::cpp_namespace](). /// \effects Registers a new [cppast::cpp_namespace]().
/// \notes The namespace object must live as long as the index lives. /// \notes The namespace object must live as long as the index lives.
/// \notes This operation is thread safe. /// \notes This operation is thread safe.
void register_namespace(cpp_entity_id id, void register_namespace(cpp_entity_id id, type_safe::object_ref<const cpp_namespace> ns) const;
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](). /// \returns A [ts::optional_ref]() corresponding to the entity(/ies) of the given
/// If no definition has been registered, it return the first declaration that was registered. /// [cppast::cpp_entity_id](). If no definition has been registered, it return the first
/// If the id resolves to a namespaces, returns an empty optional. /// declaration that was registered. If the id resolves to a namespaces, returns an empty
/// \notes This operation is thread safe. /// optional. \notes This operation is thread safe.
type_safe::optional_ref<const cpp_entity> lookup(const cpp_entity_id& id) const noexcept; 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](). /// \returns A [ts::optional_ref]() corresponding to the entity of the given
/// If no definition has been registered, it returns an empty optional. /// [cppast::cpp_entity_id](). If no definition has been registered, it returns an empty
/// \notes This operation is thread safe. /// optional. \notes This operation is thread safe.
type_safe::optional_ref<const cpp_entity> lookup_definition(const cpp_entity_id& id) const type_safe::optional_ref<const cpp_entity> lookup_definition(const cpp_entity_id& id) const
noexcept; noexcept;
/// \returns A [ts::array_ref]() of references to all namespaces matching the given [cppast::cpp_entity_id](). /// \returns A [ts::array_ref]() of references to all namespaces matching the given
/// If no namespace is found, it returns an empty array reference. /// [cppast::cpp_entity_id](). If no namespace is found, it returns an empty array reference.
/// \notes This operation is thread safe. /// \notes This operation is thread safe.
auto lookup_namespace(const cpp_entity_id& id) const noexcept auto lookup_namespace(const cpp_entity_id& id) const noexcept
-> type_safe::array_ref<type_safe::object_ref<const cpp_namespace>>; -> type_safe::array_ref<type_safe::object_ref<const cpp_namespace>>;
private: private:
struct hash struct hash
{ {
std::size_t operator()(const cpp_entity_id& id) const noexcept std::size_t operator()(const cpp_entity_id& id) const noexcept
@ -130,8 +129,7 @@ namespace cppast
value(type_safe::object_ref<const cpp_entity> e, bool def) value(type_safe::object_ref<const cpp_entity> e, bool def)
: entity(std::move(e)), is_definition(def) : entity(std::move(e)), is_definition(def)
{ {}
}
}; };
mutable std::mutex mutex_; mutable std::mutex mutex_;
@ -139,7 +137,7 @@ namespace cppast
mutable std::unordered_map<cpp_entity_id, mutable std::unordered_map<cpp_entity_id,
std::vector<type_safe::object_ref<const cpp_namespace>>, hash> std::vector<type_safe::object_ref<const cpp_namespace>>, hash>
ns_; ns_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED #endif // CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED

View file

@ -9,9 +9,9 @@
namespace cppast namespace cppast
{ {
/// All possible kinds of C++ entities. /// All possible kinds of C++ entities.
enum class cpp_entity_kind enum class cpp_entity_kind
{ {
file_t, file_t,
macro_parameter_t, macro_parameter_t,
@ -63,27 +63,27 @@ namespace cppast
unexposed_t, unexposed_t,
count, count,
}; };
/// \returns A human readable string describing the entity kind. /// \returns A human readable string describing the entity kind.
const char* to_string(cpp_entity_kind kind) noexcept; const char* to_string(cpp_entity_kind kind) noexcept;
/// \returns Whether or not a given entity kind is a C++ function, /// \returns Whether or not a given entity kind is a C++ function,
/// that is, it dervies from [cppast::cpp_function_base](). /// that is, it dervies from [cppast::cpp_function_base]().
bool is_function(cpp_entity_kind kind) noexcept; bool is_function(cpp_entity_kind kind) noexcept;
/// \returns Whether or not a given entity kind is a C++ (template) parameter. /// \returns Whether or not a given entity kind is a C++ (template) parameter.
bool is_parameter(cpp_entity_kind kind) noexcept; bool is_parameter(cpp_entity_kind kind) noexcept;
/// \returns Whether or not a given entity kind is a C++ template, /// \returns Whether or not a given entity kind is a C++ template,
/// that is, it dervies from [cppast::cpp_template](). /// that is, it dervies from [cppast::cpp_template]().
/// \notes A template template parameter is not considered a template for this function. /// \notes A template template parameter is not considered a template for this function.
/// \notes Template specializations are also considered templates here. /// \notes Template specializations are also considered templates here.
bool is_template(cpp_entity_kind kind) noexcept; bool is_template(cpp_entity_kind kind) noexcept;
/// \returns Whether or not a given entity kind is a specialization of a C++ template, /// \returns Whether or not a given entity kind is a specialization of a C++ template,
/// that is, it derives from [cppast::cpp_template_specialization](). /// that is, it derives from [cppast::cpp_template_specialization]().
bool is_template_specialization(cpp_entity_kind kind) noexcept; bool is_template_specialization(cpp_entity_kind kind) noexcept;
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED #endif // CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED

View file

@ -9,34 +9,32 @@
#include <type_safe/variant.hpp> #include <type_safe/variant.hpp>
#include <cppast/detail/assert.hpp>
#include <cppast/cpp_entity_index.hpp> #include <cppast/cpp_entity_index.hpp>
#include <cppast/detail/assert.hpp>
namespace cppast namespace cppast
{ {
enum class cpp_entity_kind; enum class cpp_entity_kind;
/// A basic reference to some kind of [cppast::cpp_entity](). /// A basic reference to some kind of [cppast::cpp_entity]().
/// ///
/// It can either refer to a single [cppast::cpp_entity]() /// It can either refer to a single [cppast::cpp_entity]()
/// or multiple. /// or multiple.
/// In the later case it is *overloaded*. /// In the later case it is *overloaded*.
template <typename T, typename Predicate> template <typename T, typename Predicate>
class basic_cpp_entity_ref class basic_cpp_entity_ref
{ {
public: public:
/// \effects Creates it giving it the target id and name. /// \effects Creates it giving it the target id and name.
basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name) basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name)
: target_(std::move(target_id)), name_(std::move(target_name)) : target_(std::move(target_id)), name_(std::move(target_name))
{ {}
}
/// \effects Creates it giving it multiple target ids and name. /// \effects Creates it giving it multiple target ids and name.
/// \notes This is to refer to an overloaded function. /// \notes This is to refer to an overloaded function.
basic_cpp_entity_ref(std::vector<cpp_entity_id> target_ids, std::string target_name) 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)) : target_(std::move(target_ids)), name_(std::move(target_name))
{ {}
}
/// \returns The name of the reference, as spelled in the source code. /// \returns The name of the reference, as spelled in the source code.
const std::string& name() const noexcept const std::string& name() const noexcept
@ -82,7 +80,7 @@ namespace cppast
return result; return result;
} }
private: private:
void get_impl(std::true_type, std::vector<type_safe::object_ref<const T>>& result, void get_impl(std::true_type, std::vector<type_safe::object_ref<const T>>& result,
const cpp_entity_index& idx) const const cpp_entity_index& idx) const
{ {
@ -110,11 +108,11 @@ namespace cppast
type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_; type_safe::variant<cpp_entity_id, std::vector<cpp_entity_id>> target_;
std::string name_; std::string name_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_entity_ref_predicate struct cpp_entity_ref_predicate
{ {
bool operator()(const cpp_entity&) bool operator()(const cpp_entity&)
@ -122,10 +120,10 @@ namespace cppast
return true; return true;
} }
}; };
} } // namespace detail
/// A [cppast::basic_cpp_entity_ref]() to any [cppast::cpp_entity](). /// 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>; using cpp_entity_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_entity_ref_predicate>;
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENTITY_REF_HPP_INCLUDED #endif // CPPAST_CPP_ENTITY_REF_HPP_INCLUDED

View file

@ -9,25 +9,25 @@
#include <type_safe/optional_ref.hpp> #include <type_safe/optional_ref.hpp>
#include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_container.hpp> #include <cppast/cpp_entity_container.hpp>
#include <cppast/cpp_entity_index.hpp> #include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity.hpp>
#include <cppast/cpp_expression.hpp> #include <cppast/cpp_expression.hpp>
#include <cppast/cpp_forward_declarable.hpp> #include <cppast/cpp_forward_declarable.hpp>
#include <cppast/cpp_type.hpp> #include <cppast/cpp_type.hpp>
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling the value of an [cppast::cpp_enum](). /// A [cppast::cpp_entity]() modelling the value of an [cppast::cpp_enum]().
class cpp_enum_value final : public cpp_entity class cpp_enum_value final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered enum value. /// \returns A newly created and registered enum value.
/// \notes `value` may be `nullptr`, in which case the enum has an implicit value. /// \notes `value` may be `nullptr`, in which case the enum has an implicit value.
static std::unique_ptr<cpp_enum_value> build( static std::unique_ptr<cpp_enum_value> build(const cpp_entity_index& idx, cpp_entity_id id,
const cpp_entity_index& idx, cpp_entity_id id, std::string name, std::string name,
std::unique_ptr<cpp_expression> value = nullptr); std::unique_ptr<cpp_expression> value = nullptr);
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the enum value. /// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the enum value.
@ -37,26 +37,25 @@ namespace cppast
return type_safe::opt_cref(value_.get()); return type_safe::opt_cref(value_.get());
} }
private: private:
cpp_enum_value(std::string name, std::unique_ptr<cpp_expression> value) cpp_enum_value(std::string name, std::unique_ptr<cpp_expression> value)
: cpp_entity(std::move(name)), value_(std::move(value)) : cpp_entity(std::move(name)), value_(std::move(value))
{ {}
}
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> value_; std::unique_ptr<cpp_expression> value_;
}; };
/// A [cppast::cpp_entity]() modelling a C++ enumeration. /// A [cppast::cpp_entity]() modelling a C++ enumeration.
/// ///
/// This can either be a definition or just a forward declaration. /// This can either be a definition or just a forward declaration.
/// If it is just forward declared, it will not have any children. /// If it is just forward declared, it will not have any children.
class cpp_enum final : public cpp_entity, class cpp_enum final : public cpp_entity,
public cpp_entity_container<cpp_enum, cpp_enum_value>, public cpp_entity_container<cpp_enum, cpp_enum_value>,
public cpp_forward_declarable public cpp_forward_declarable
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_enum](). /// Builds a [cppast::cpp_enum]().
@ -64,11 +63,9 @@ namespace cppast
{ {
public: public:
/// \effects Sets the name, underlying type and whether it is scoped. /// \effects Sets the name, underlying type and whether it is scoped.
builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type, builder(std::string name, bool scoped, std::unique_ptr<cpp_type> type, bool explicit_type)
bool explicit_type)
: enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped)) : enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped))
{ {}
}
/// \effects Adds a [cppast::cpp_enum_value](). /// \effects Adds a [cppast::cpp_enum_value]().
void add_value(std::unique_ptr<cpp_enum_value> value) void add_value(std::unique_ptr<cpp_enum_value> value)
@ -126,14 +123,10 @@ namespace cppast
return scoped_; return scoped_;
} }
private: private:
cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool type_given, bool scoped) cpp_enum(std::string name, std::unique_ptr<cpp_type> type, bool type_given, bool scoped)
: cpp_entity(std::move(name)), : cpp_entity(std::move(name)), type_(std::move(type)), scoped_(scoped), type_given_(type_given)
type_(std::move(type)), {}
scoped_(scoped),
type_given_(type_given)
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
@ -141,7 +134,7 @@ namespace cppast
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
bool scoped_, type_given_; bool scoped_, type_given_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_ENUM_HPP_INCLUDED #endif // CPPAST_CPP_ENUM_HPP_INCLUDED

View file

@ -13,18 +13,18 @@
namespace cppast namespace cppast
{ {
/// The kind of a [cppast::cpp_expression](). /// The kind of a [cppast::cpp_expression]().
enum class cpp_expression_kind enum class cpp_expression_kind
{ {
literal_t, literal_t,
unexposed_t, unexposed_t,
}; };
/// Base class for all C++ expressions. /// Base class for all C++ expressions.
class cpp_expression class cpp_expression
{ {
public: public:
cpp_expression(const cpp_expression&) = delete; cpp_expression(const cpp_expression&) = delete;
cpp_expression& operator=(const cpp_expression&) = delete; cpp_expression& operator=(const cpp_expression&) = delete;
@ -53,13 +53,14 @@ namespace cppast
/// User data is just some kind of pointer, there are no requirements. /// User data is just some kind of pointer, there are no requirements.
/// The class will do no lifetime management. /// 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. /// 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 void set_user_data(void* data) const noexcept
{ {
user_data_ = data; user_data_ = data;
} }
protected: protected:
/// \effects Creates it given the type. /// \effects Creates it given the type.
/// \requires The type must not be `nullptr`. /// \requires The type must not be `nullptr`.
cpp_expression(std::unique_ptr<cpp_type> type) : type_(std::move(type)), user_data_(nullptr) cpp_expression(std::unique_ptr<cpp_type> type) : type_(std::move(type)), user_data_(nullptr)
@ -67,20 +68,20 @@ namespace cppast
DEBUG_ASSERT(type_ != nullptr, detail::precondition_error_handler{}); DEBUG_ASSERT(type_ != nullptr, detail::precondition_error_handler{});
} }
private: private:
/// \returns The [cppast::cpp_expression_kind](). /// \returns The [cppast::cpp_expression_kind]().
virtual cpp_expression_kind do_get_kind() const noexcept = 0; virtual cpp_expression_kind do_get_kind() const noexcept = 0;
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
mutable std::atomic<void*> user_data_; mutable std::atomic<void*> user_data_;
}; };
/// An unexposed [cppast::cpp_expression](). /// An unexposed [cppast::cpp_expression]().
/// ///
/// There is no further information than a string available. /// There is no further information than a string available.
class cpp_unexposed_expression final : public cpp_expression class cpp_unexposed_expression final : public cpp_expression
{ {
public: public:
/// \returns A newly created unexposed expression. /// \returns A newly created unexposed expression.
static std::unique_ptr<cpp_unexposed_expression> build(std::unique_ptr<cpp_type> type, static std::unique_ptr<cpp_unexposed_expression> build(std::unique_ptr<cpp_type> type,
cpp_token_string str) cpp_token_string str)
@ -95,11 +96,10 @@ namespace cppast
return str_; return str_;
} }
private: private:
cpp_unexposed_expression(std::unique_ptr<cpp_type> type, cpp_token_string str) cpp_unexposed_expression(std::unique_ptr<cpp_type> type, cpp_token_string str)
: cpp_expression(std::move(type)), str_(std::move(str)) : cpp_expression(std::move(type)), str_(std::move(str))
{ {}
}
cpp_expression_kind do_get_kind() const noexcept override cpp_expression_kind do_get_kind() const noexcept override
{ {
@ -107,12 +107,12 @@ namespace cppast
} }
cpp_token_string str_; cpp_token_string str_;
}; };
/// A [cppast::cpp_expression]() that is a literal. /// A [cppast::cpp_expression]() that is a literal.
class cpp_literal_expression final : public cpp_expression class cpp_literal_expression final : public cpp_expression
{ {
public: public:
/// \returns A newly created literal expression. /// \returns A newly created literal expression.
static std::unique_ptr<cpp_literal_expression> build(std::unique_ptr<cpp_type> type, static std::unique_ptr<cpp_literal_expression> build(std::unique_ptr<cpp_type> type,
std::string value) std::string value)
@ -127,11 +127,10 @@ namespace cppast
return value_; return value_;
} }
private: private:
cpp_literal_expression(std::unique_ptr<cpp_type> type, std::string value) cpp_literal_expression(std::unique_ptr<cpp_type> type, std::string value)
: cpp_expression(std::move(type)), value_(std::move(value)) : cpp_expression(std::move(type)), value_(std::move(value))
{ {}
}
cpp_expression_kind do_get_kind() const noexcept override cpp_expression_kind do_get_kind() const noexcept override
{ {
@ -139,13 +138,13 @@ namespace cppast
} }
std::string value_; std::string value_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
void write_expression(code_generator::output& output, const cpp_expression& expr); void write_expression(code_generator::output& output, const cpp_expression& expr);
} // namespace detail } // namespace detail
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_EXPRESSION_HPP_INCLUDED #endif // CPPAST_CPP_EXPRESSION_HPP_INCLUDED

View file

@ -7,30 +7,27 @@
#include <vector> #include <vector>
#include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity_container.hpp> #include <cppast/cpp_entity_container.hpp>
#include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity_ref.hpp> #include <cppast/cpp_entity_ref.hpp>
namespace cppast namespace cppast
{ {
/// An unmatched documentation comment. /// An unmatched documentation comment.
struct cpp_doc_comment struct cpp_doc_comment
{ {
std::string content; std::string content;
unsigned line; unsigned line;
cpp_doc_comment(std::string content, unsigned line) cpp_doc_comment(std::string content, unsigned line) : content(std::move(content)), line(line) {}
: content(std::move(content)), line(line) };
{
}
};
/// A [cppast::cpp_entity]() modelling a file. /// A [cppast::cpp_entity]() modelling a file.
/// ///
/// This is the top-level entity of the AST. /// This is the top-level entity of the AST.
class cpp_file final : public cpp_entity, public cpp_entity_container<cpp_file, cpp_entity> class cpp_file final : public cpp_entity, public cpp_entity_container<cpp_file, cpp_entity>
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_file](). /// Builds a [cppast::cpp_file]().
@ -77,26 +74,26 @@ namespace cppast
return type_safe::ref(comments_.data(), comments_.size()); return type_safe::ref(comments_.data(), comments_.size());
} }
private: private:
cpp_file(std::string name) : cpp_entity(std::move(name)) {} cpp_file(std::string name) : cpp_entity(std::move(name)) {}
/// \returns [cpp_entity_type::file_t](). /// \returns [cpp_entity_type::file_t]().
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
std::vector<cpp_doc_comment> comments_; std::vector<cpp_doc_comment> comments_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_file_ref_predicate struct cpp_file_ref_predicate
{ {
bool operator()(const cpp_entity& e); bool operator()(const cpp_entity& e);
}; };
} // namespace detail } // namespace detail
/// A reference to a [cppast::cpp_file](). /// A reference to a [cppast::cpp_file]().
using cpp_file_ref = basic_cpp_entity_ref<cpp_file, detail::cpp_file_ref_predicate>; using cpp_file_ref = basic_cpp_entity_ref<cpp_file, detail::cpp_file_ref_predicate>;
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_FILE_HPP_INCLUDED #endif // CPPAST_CPP_FILE_HPP_INCLUDED

View file

@ -14,14 +14,14 @@
namespace cppast namespace cppast
{ {
/// Mixin base class for all entities that can have a forward declaration. /// Mixin base class for all entities that can have a forward declaration.
/// ///
/// Examples are [cppast::cpp_enum]() or [cppast::cpp_class](), /// Examples are [cppast::cpp_enum]() or [cppast::cpp_class](),
/// but also [cppast::cpp_function_base](). /// but also [cppast::cpp_function_base]().
/// Those entities can have multiple declarations and one definition. /// Those entities can have multiple declarations and one definition.
class cpp_forward_declarable class cpp_forward_declarable
{ {
public: public:
/// \returns Whether or not the entity is the definition. /// \returns Whether or not the entity is the definition.
bool is_definition() const noexcept bool is_definition() const noexcept
{ {
@ -57,7 +57,7 @@ namespace cppast
return type_safe::copy(semantic_parent_.map(&cpp_entity_ref::name)).value_or(""); return type_safe::copy(semantic_parent_.map(&cpp_entity_ref::name)).value_or("");
} }
protected: protected:
/// \effects Marks the entity as definition. /// \effects Marks the entity as definition.
/// \notes If it is not a definition, /// \notes If it is not a definition,
/// [*set_definition]() must be called. /// [*set_definition]() must be called.
@ -78,39 +78,38 @@ namespace cppast
semantic_parent_ = std::move(semantic_parent); semantic_parent_ = std::move(semantic_parent);
} }
private: private:
type_safe::optional<cpp_entity_ref> semantic_parent_; type_safe::optional<cpp_entity_ref> semantic_parent_;
type_safe::optional<cpp_entity_id> definition_; type_safe::optional<cpp_entity_id> definition_;
}; };
/// \returns Whether or not the given entity is a definition. /// \returns Whether or not the given entity is a definition.
bool is_definition(const cpp_entity& e) noexcept; bool is_definition(const cpp_entity& e) noexcept;
class cpp_enum; class cpp_enum;
class cpp_class; class cpp_class;
class cpp_variable; class cpp_variable;
class cpp_function_base; class cpp_function_base;
/// Gets the definition of an entity. /// Gets the definition of an entity.
/// \returns A [ts::optional_ref]() to the entity that is the definition. /// \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), /// If the entity is a definition or not derived from [cppast::cpp_forward_declarable]() (only valid
/// returns a reference to the entity itself. /// for the generic entity overload), returns a reference to the entity itself. Otherwise lookups
/// Otherwise lookups the definition id and returns it. /// the definition id and returns it. \notes The return value will only be `nullptr`, if the
/// \notes The return value will only be `nullptr`, if the definition is not registered. /// definition is not registered. \group get_definition
/// \group get_definition type_safe::optional_ref<const cpp_entity> get_definition(const cpp_entity_index& idx,
type_safe::optional_ref<const cpp_entity> get_definition(const cpp_entity_index& idx,
const cpp_entity& e); const cpp_entity& e);
/// \group get_definition /// \group get_definition
type_safe::optional_ref<const cpp_enum> get_definition(const cpp_entity_index& idx, type_safe::optional_ref<const cpp_enum> get_definition(const cpp_entity_index& idx,
const cpp_enum& e); const cpp_enum& e);
/// \group get_definition /// \group get_definition
type_safe::optional_ref<const cpp_class> get_definition(const cpp_entity_index& idx, type_safe::optional_ref<const cpp_class> get_definition(const cpp_entity_index& idx,
const cpp_class& e); const cpp_class& e);
/// \group get_definition /// \group get_definition
type_safe::optional_ref<const cpp_variable> get_definition(const cpp_entity_index& idx, type_safe::optional_ref<const cpp_variable> get_definition(const cpp_entity_index& idx,
const cpp_variable& e); const cpp_variable& e);
/// \group get_definition /// \group get_definition
type_safe::optional_ref<const cpp_function_base> get_definition(const cpp_entity_index& idx, type_safe::optional_ref<const cpp_function_base> get_definition(const cpp_entity_index& idx,
const cpp_function_base& e); const cpp_function_base& e);
} // namespace cppast } // namespace cppast

View file

@ -13,13 +13,13 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() representing a friend declaration. /// A [cppast::cpp_entity]() representing a friend declaration.
/// ///
/// It can either declare or define a `friend` function (template), declare a `friend` class, /// It can either declare or define a `friend` function (template), declare a `friend` class,
/// or refer to an existing type. /// or refer to an existing type.
class cpp_friend : public cpp_entity, private cpp_entity_container<cpp_friend, cpp_entity> class cpp_friend : public cpp_entity, private cpp_entity_container<cpp_friend, cpp_entity>
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created friend declaring the given entity as `friend`. /// \returns A newly created friend declaring the given entity as `friend`.
@ -51,7 +51,7 @@ namespace cppast
return type_safe::opt_ref(type_.get()); return type_safe::opt_ref(type_.get());
} }
private: private:
cpp_friend(std::unique_ptr<cpp_entity> e) : cpp_entity("") cpp_friend(std::unique_ptr<cpp_entity> e) : cpp_entity("")
{ {
add_child(std::move(e)); add_child(std::move(e));
@ -64,7 +64,7 @@ namespace cppast
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 } // namespace cppast
#endif // CPPAST_CPP_FRIEND_HPP_INCLUDED #endif // CPPAST_CPP_FRIEND_HPP_INCLUDED

View file

@ -5,69 +5,72 @@
#ifndef CPPAST_CPP_FUNCTION_HPP_INCLUDED #ifndef CPPAST_CPP_FUNCTION_HPP_INCLUDED
#define 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_entity.hpp>
#include <cppast/cpp_forward_declarable.hpp> #include <cppast/cpp_forward_declarable.hpp>
#include <cppast/cpp_storage_class_specifiers.hpp> #include <cppast/cpp_storage_class_specifiers.hpp>
#include <cppast/cpp_variable_base.hpp> #include <cppast/cpp_variable_base.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a function parameter. /// A [cppast::cpp_entity]() modelling a function parameter.
class cpp_function_parameter final : public cpp_entity, public cpp_variable_base class cpp_function_parameter final : public cpp_entity, public cpp_variable_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered function parameter. /// \returns A newly created and registered function parameter.
static std::unique_ptr<cpp_function_parameter> build( static std::unique_ptr<cpp_function_parameter> build(const cpp_entity_index& idx,
const cpp_entity_index& idx, cpp_entity_id id, std::string name, cpp_entity_id id, std::string name,
std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def = nullptr); std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_expression> def
= nullptr);
/// \returns A newly created unnamed function parameter. /// \returns A newly created unnamed function parameter.
/// \notes It will not be registered, as nothing can refer to it. /// \notes It will not be registered, as nothing can refer to it.
static std::unique_ptr<cpp_function_parameter> build( static std::unique_ptr<cpp_function_parameter> build(std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def = nullptr); std::unique_ptr<cpp_expression> def
= nullptr);
private: private:
cpp_function_parameter(std::string name, std::unique_ptr<cpp_type> type, cpp_function_parameter(std::string name, std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_expression> def) std::unique_ptr<cpp_expression> def)
: cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(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; cpp_entity_kind do_get_entity_kind() const noexcept override;
}; };
/// The kinds of function bodies of a [cppast::cpp_function_base](). /// The kinds of function bodies of a [cppast::cpp_function_base]().
enum cpp_function_body_kind enum cpp_function_body_kind
{ {
cpp_function_declaration, //< Just a declaration. cpp_function_declaration, //< Just a declaration.
cpp_function_definition, //< Regular definition. cpp_function_definition, //< Regular definition.
cpp_function_defaulted, //< Defaulted definition. cpp_function_defaulted, //< Defaulted definition.
cpp_function_deleted, //< Deleted definition. cpp_function_deleted, //< Deleted definition.
}; };
/// \returns Whether or not the function body is a declaration, /// \returns Whether or not the function body is a declaration,
/// without a definition. /// without a definition.
inline bool is_declaration(cpp_function_body_kind body) noexcept inline bool is_declaration(cpp_function_body_kind body) noexcept
{ {
return body == cpp_function_declaration; return body == cpp_function_declaration;
} }
/// \returns Whether or not the function body is a definition. /// \returns Whether or not the function body is a definition.
inline bool is_definition(cpp_function_body_kind body) noexcept inline bool is_definition(cpp_function_body_kind body) noexcept
{ {
return !is_declaration(body); return !is_declaration(body);
} }
/// Base class for all entities that are functions. /// Base class for all entities that are functions.
/// ///
/// It contains arguments and common flags. /// It contains arguments and common flags.
class cpp_function_base : public cpp_entity, public cpp_forward_declarable class cpp_function_base : public cpp_entity, public cpp_forward_declarable
{ {
public: public:
/// \returns An iteratable object iterating over the [cppast::cpp_function__parameter]() entities. /// \returns An iteratable object iterating over the [cppast::cpp_function__parameter]()
/// entities.
detail::iteratable_intrusive_list<cpp_function_parameter> parameters() const noexcept detail::iteratable_intrusive_list<cpp_function_parameter> parameters() const noexcept
{ {
return type_safe::ref(parameters_); return type_safe::ref(parameters_);
@ -80,9 +83,10 @@ namespace cppast
return body_; return body_;
} }
/// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the given `noexcept` condition. /// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the given
/// \notes If this returns `nullptr`, the function has the implicit noexcept value (i.e. none, unless it is a destructor). /// `noexcept` condition. \notes If this returns `nullptr`, the function has the implicit
/// \notes There is no way to distinguish between `noexcept` and `noexcept(true)`. /// 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 type_safe::optional_ref<const cpp_expression> noexcept_condition() const noexcept
{ {
return type_safe::opt_cref(noexcept_expr_.get()); return type_safe::opt_cref(noexcept_expr_.get());
@ -102,7 +106,7 @@ namespace cppast
return do_get_signature(); return do_get_signature();
} }
protected: protected:
/// Builder class for functions. /// Builder class for functions.
/// ///
/// Inherit from it to provide additional setter. /// Inherit from it to provide additional setter.
@ -117,8 +121,7 @@ namespace cppast
void add_parameter(std::unique_ptr<cpp_function_parameter> parameter) void add_parameter(std::unique_ptr<cpp_function_parameter> parameter)
{ {
static_cast<cpp_function_base&>(*function).parameters_.push_back(*function, static_cast<cpp_function_base&>(*function).parameters_.push_back(*function,
std::move( std::move(parameter));
parameter));
} }
/// \effects Marks the function as variadic. /// \effects Marks the function as variadic.
@ -179,27 +182,26 @@ namespace cppast
cpp_function_base(std::string name) cpp_function_base(std::string name)
: cpp_entity(std::move(name)), body_(cpp_function_declaration), variadic_(false) : cpp_entity(std::move(name)), body_(cpp_function_declaration), variadic_(false)
{ {}
}
protected: protected:
/// \returns The signature, it is called by [*signature()](). /// \returns The signature, it is called by [*signature()]().
virtual std::string do_get_signature() const; virtual std::string do_get_signature() const;
private: private:
detail::intrusive_list<cpp_function_parameter> parameters_; detail::intrusive_list<cpp_function_parameter> parameters_;
std::unique_ptr<cpp_expression> noexcept_expr_; std::unique_ptr<cpp_expression> noexcept_expr_;
cpp_function_body_kind body_; cpp_function_body_kind body_;
bool variadic_; bool variadic_;
}; };
/// A [cppast::cpp_entity]() modelling a C++ function. /// A [cppast::cpp_entity]() modelling a C++ function.
/// \notes This is not a member function, /// \notes This is not a member function,
/// use [cppast::cpp_member_function]() for that. /// use [cppast::cpp_member_function]() for that.
/// It can be a `static` function of a class, however. /// It can be a `static` function of a class, however.
class cpp_function final : public cpp_function_base class cpp_function final : public cpp_function_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_function](). /// Builds a [cppast::cpp_function]().
@ -246,21 +248,18 @@ namespace cppast
return constexpr_; return constexpr_;
} }
private: private:
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_function(std::string name, std::unique_ptr<cpp_type> ret) cpp_function(std::string name, std::unique_ptr<cpp_type> ret)
: cpp_function_base(std::move(name)), : cpp_function_base(std::move(name)), return_type_(std::move(ret)),
return_type_(std::move(ret)), storage_(cpp_storage_class_auto), constexpr_(false)
storage_(cpp_storage_class_auto), {}
constexpr_(false)
{
}
std::unique_ptr<cpp_type> return_type_; std::unique_ptr<cpp_type> return_type_;
cpp_storage_class_specifiers storage_; cpp_storage_class_specifiers storage_;
bool constexpr_; bool constexpr_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_FUNCTION_HPP_INCLUDED #endif // CPPAST_CPP_FUNCTION_HPP_INCLUDED

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a function template. /// A [cppast::cpp_entity]() modelling a function template.
class cpp_function_template final : public cpp_template class cpp_function_template final : public cpp_template
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_function_template](). /// Builder for [cppast::cpp_function_template]().
@ -29,21 +29,20 @@ namespace cppast
return static_cast<const cpp_function_base&>(*begin()); return static_cast<const cpp_function_base&>(*begin());
} }
private: private:
cpp_function_template(std::unique_ptr<cpp_function_base> func) cpp_function_template(std::unique_ptr<cpp_function_base> func)
: cpp_template(std::unique_ptr<cpp_entity>(func.release())) : cpp_template(std::unique_ptr<cpp_entity>(func.release()))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_builder<cpp_function_template, cpp_function_base>; friend basic_builder<cpp_function_template, cpp_function_base>;
}; };
/// A [cppast::cpp_entity]() modelling a function template specialization. /// A [cppast::cpp_entity]() modelling a function template specialization.
class cpp_function_template_specialization final : public cpp_template_specialization class cpp_function_template_specialization final : public cpp_template_specialization
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_function_template_specialization](). /// Builder for [cppast::cpp_function_template_specialization]().
@ -63,17 +62,16 @@ namespace cppast
return static_cast<const cpp_function_base&>(*begin()); return static_cast<const cpp_function_base&>(*begin());
} }
private: private:
cpp_function_template_specialization(std::unique_ptr<cpp_function_base> func, cpp_function_template_specialization(std::unique_ptr<cpp_function_base> func,
cpp_template_ref primary) cpp_template_ref primary)
: cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary) : cpp_template_specialization(std::unique_ptr<cpp_entity>(func.release()), primary)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend specialization_builder<cpp_function_template_specialization, cpp_function_base>; friend specialization_builder<cpp_function_template_specialization, cpp_function_base>;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED #endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED

View file

@ -9,12 +9,12 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_type]() that is a function. /// A [cppast::cpp_type]() that is a function.
/// ///
/// A function pointer is created by wrapping it in [cppast::cpp_pointer_type](). /// A function pointer is created by wrapping it in [cppast::cpp_pointer_type]().
class cpp_function_type final : public cpp_type class cpp_function_type final : public cpp_type
{ {
public: public:
/// Builds a [cppast::cpp_function_type](). /// Builds a [cppast::cpp_function_type]().
class builder class builder
{ {
@ -22,8 +22,7 @@ namespace cppast
/// \effects Sets the return type. /// \effects Sets the return type.
explicit builder(std::unique_ptr<cpp_type> return_type) explicit builder(std::unique_ptr<cpp_type> return_type)
: func_(new cpp_function_type(std::move(return_type))) : func_(new cpp_function_type(std::move(return_type)))
{ {}
}
/// \effects Adds an parameter type. /// \effects Adds an parameter type.
void add_parameter(std::unique_ptr<cpp_type> arg) void add_parameter(std::unique_ptr<cpp_type> arg)
@ -65,11 +64,10 @@ namespace cppast
return variadic_; return variadic_;
} }
private: private:
cpp_function_type(std::unique_ptr<cpp_type> return_type) cpp_function_type(std::unique_ptr<cpp_type> return_type)
: return_type_(std::move(return_type)), variadic_(false) : return_type_(std::move(return_type)), variadic_(false)
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -79,16 +77,17 @@ namespace cppast
std::unique_ptr<cpp_type> return_type_; std::unique_ptr<cpp_type> return_type_;
detail::intrusive_list<cpp_type> parameters_; detail::intrusive_list<cpp_type> parameters_;
bool variadic_; bool variadic_;
}; };
/// A [cppast::cpp_type]() that is a member function. /// 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 cv qualifier is created by wrapping it in
/// A member function with reference qualifier is created by wrapping it in [cppast::cpp_reference_type](). /// [cppast::cpp_cv_qualified_type](). A member function with reference qualifier is created by
/// A member function pointer is created by wrapping it in [cppast::cpp_pointer_type](). /// wrapping it in [cppast::cpp_reference_type](). A member function pointer is created by wrapping
class cpp_member_function_type final : public cpp_type /// it in [cppast::cpp_pointer_type]().
{ class cpp_member_function_type final : public cpp_type
public: {
public:
/// Builds a [cppast::cpp_member_function_type](). /// Builds a [cppast::cpp_member_function_type]().
class builder class builder
{ {
@ -96,8 +95,7 @@ namespace cppast
/// \effects Sets the class and return type. /// \effects Sets the class and return type.
builder(std::unique_ptr<cpp_type> class_type, std::unique_ptr<cpp_type> 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))) : func_(new cpp_member_function_type(std::move(class_type), std::move(return_type)))
{ {}
}
/// \effects Adds a parameter type. /// \effects Adds a parameter type.
void add_parameter(std::unique_ptr<cpp_type> arg) void add_parameter(std::unique_ptr<cpp_type> arg)
@ -145,12 +143,11 @@ namespace cppast
return variadic_; return variadic_;
} }
private: private:
cpp_member_function_type(std::unique_ptr<cpp_type> class_type, cpp_member_function_type(std::unique_ptr<cpp_type> class_type,
std::unique_ptr<cpp_type> return_type) std::unique_ptr<cpp_type> return_type)
: class_type_(std::move(class_type)), return_type_(std::move(return_type)), variadic_(false) : class_type_(std::move(class_type)), return_type_(std::move(return_type)), variadic_(false)
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -160,14 +157,14 @@ namespace cppast
std::unique_ptr<cpp_type> class_type_, return_type_; std::unique_ptr<cpp_type> class_type_, return_type_;
detail::intrusive_list<cpp_type> parameters_; detail::intrusive_list<cpp_type> parameters_;
bool variadic_; bool variadic_;
}; };
/// A [cppast::cpp_type]() that is a member object. /// A [cppast::cpp_type]() that is a member object.
/// ///
/// A member object pointer is created by wrapping it in [cppast::cpp_pointer_type](). /// A member object pointer is created by wrapping it in [cppast::cpp_pointer_type]().
class cpp_member_object_type final : public cpp_type class cpp_member_object_type final : public cpp_type
{ {
public: public:
/// \returns A newly created member object type. /// \returns A newly created member object type.
static std::unique_ptr<cpp_member_object_type> build(std::unique_ptr<cpp_type> class_type, static std::unique_ptr<cpp_member_object_type> build(std::unique_ptr<cpp_type> class_type,
std::unique_ptr<cpp_type> object_type) std::unique_ptr<cpp_type> object_type)
@ -188,12 +185,11 @@ namespace cppast
return *object_type_; return *object_type_;
} }
private: private:
cpp_member_object_type(std::unique_ptr<cpp_type> class_type, cpp_member_object_type(std::unique_ptr<cpp_type> class_type,
std::unique_ptr<cpp_type> object_type) std::unique_ptr<cpp_type> object_type)
: class_type_(std::move(class_type)), object_type_(std::move(object_type)) : class_type_(std::move(class_type)), object_type_(std::move(object_type))
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -201,7 +197,7 @@ namespace cppast
} }
std::unique_ptr<cpp_type> class_type_, object_type_; std::unique_ptr<cpp_type> class_type_, object_type_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_FUNCTION_TYPE_HPP_INCLUDED #endif // CPPAST_CPP_FUNCTION_TYPE_HPP_INCLUDED

View file

@ -10,11 +10,11 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a language linkage. /// A [cppast::cpp_entity]() modelling a language linkage.
class cpp_language_linkage final : public cpp_entity, class cpp_language_linkage final : public cpp_entity,
public cpp_entity_container<cpp_language_linkage, cpp_entity> public cpp_entity_container<cpp_language_linkage, cpp_entity>
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_language_linkage](). /// Builds a [cppast::cpp_language_linkage]().
@ -22,9 +22,7 @@ namespace cppast
{ {
public: public:
/// \effects Sets the name, that is the kind of language linkage. /// \effects Sets the name, that is the kind of language linkage.
explicit builder(std::string name) : linkage_(new cpp_language_linkage(std::move(name))) explicit builder(std::string name) : linkage_(new cpp_language_linkage(std::move(name))) {}
{
}
/// \effects Adds an entity to the language linkage. /// \effects Adds an entity to the language linkage.
void add_child(std::unique_ptr<cpp_entity> child) void add_child(std::unique_ptr<cpp_entity> child)
@ -52,11 +50,11 @@ namespace cppast
/// \returns `true` if the linkage is a block, `false` otherwise. /// \returns `true` if the linkage is a block, `false` otherwise.
bool is_block() const noexcept; bool is_block() const noexcept;
private: private:
using cpp_entity::cpp_entity; using cpp_entity::cpp_entity;
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED #endif // CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED

View file

@ -11,60 +11,59 @@
namespace cppast namespace cppast
{ {
/// The `virtual`-ness of a member function. /// The `virtual`-ness of a member function.
/// ///
/// This is a [ts::flag_set]() `enum`. /// This is a [ts::flag_set]() `enum`.
/// \notes It does not specify whether a member function is `virtual` or not, /// \notes It does not specify whether a member function is `virtual` or not,
/// only the kind of `virtual`. /// only the kind of `virtual`.
/// \notes As surprising as it may be, any of these can be used in combination, /// \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. /// i.e. you can have a `final` non-overriding function or an overriding pure `virtual` function.
enum class cpp_virtual_flags enum class cpp_virtual_flags
{ {
pure, //< Set if the function is pure. pure, //< Set if the function is pure.
override, //< Set if the function overrides a base class function. override, //< Set if the function overrides a base class function.
final, //< Set if the function is marked `final`. final, //< Set if the function is marked `final`.
_flag_set_size, //< \exclude _flag_set_size, //< \exclude
}; };
/// The `virtual` information of a member function. /// The `virtual` information of a member function.
/// ///
/// This is an optional of the combination of the [cppast::cpp_virtual_flags](). /// This is an optional of the combination of the [cppast::cpp_virtual_flags]().
/// If the optional has a value, the member function is `virtual`, /// If the optional has a value, the member function is `virtual`,
/// and the [ts::flag_set]() describes additional information. /// and the [ts::flag_set]() describes additional information.
using cpp_virtual = type_safe::optional<type_safe::flag_set<cpp_virtual_flags>>; using cpp_virtual = type_safe::optional<type_safe::flag_set<cpp_virtual_flags>>;
/// \returns Whether or not a member function is `virtual`. /// \returns Whether or not a member function is `virtual`.
inline bool is_virtual(const cpp_virtual& virt) noexcept inline bool is_virtual(const cpp_virtual& virt) noexcept
{ {
return virt.has_value(); return virt.has_value();
} }
/// \returns Whether or not a member function is pure. /// \returns Whether or not a member function is pure.
inline bool is_pure(const cpp_virtual& virt) noexcept inline bool is_pure(const cpp_virtual& virt) noexcept
{ {
return static_cast<bool>(virt.value_or(cpp_virtual_flags::final) & cpp_virtual_flags::pure); 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. /// \returns Whether or not a member function overrides another one.
inline bool is_overriding(const cpp_virtual& virt) noexcept inline bool is_overriding(const cpp_virtual& virt) noexcept
{ {
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::override);
& cpp_virtual_flags::override); }
}
/// \returns Whether or not a member function is `final`. /// \returns Whether or not a member function is `final`.
inline bool is_final(const cpp_virtual& virt) noexcept inline bool is_final(const cpp_virtual& virt) noexcept
{ {
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::final); return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::final);
} }
/// Base classes for all regular member function. /// Base classes for all regular member function.
/// ///
/// The two derived classes are [cppast::cpp_member_function]() and [cppast::cpp_conversion_op](). /// The two derived classes are [cppast::cpp_member_function]() and [cppast::cpp_conversion_op]().
class cpp_member_function_base : public cpp_function_base class cpp_member_function_base : public cpp_function_base
{ {
public: public:
/// \returns The return type of the member function. /// \returns The return type of the member function.
const cpp_type& return_type() const noexcept const cpp_type& return_type() const noexcept
{ {
@ -101,7 +100,7 @@ namespace cppast
return constexpr_; return constexpr_;
} }
protected: protected:
/// Builder class for member functions. /// Builder class for member functions.
template <typename T> template <typename T>
class basic_member_builder : public basic_builder<T> class basic_member_builder : public basic_builder<T>
@ -139,29 +138,25 @@ namespace cppast
/// \effects Sets name and return type, as well as the rest to defaults. /// \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_member_function_base(std::string name, std::unique_ptr<cpp_type> return_type)
: cpp_function_base(std::move(name)), : cpp_function_base(std::move(name)), return_type_(std::move(return_type)), cv_(cpp_cv_none),
return_type_(std::move(return_type)), ref_(cpp_ref_none), constexpr_(false)
cv_(cpp_cv_none), {}
ref_(cpp_ref_none),
constexpr_(false)
{
}
protected: protected:
std::string do_get_signature() const override; std::string do_get_signature() const override;
private: private:
std::unique_ptr<cpp_type> return_type_; std::unique_ptr<cpp_type> return_type_;
cpp_virtual virtual_; cpp_virtual virtual_;
cpp_cv cv_; cpp_cv cv_;
cpp_reference ref_; cpp_reference ref_;
bool constexpr_; bool constexpr_;
}; };
/// A [cppast::cpp_entity]() modelling a member function. /// A [cppast::cpp_entity]() modelling a member function.
class cpp_member_function final : public cpp_member_function_base class cpp_member_function final : public cpp_member_function_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_member_function](). /// Builder for [cppast::cpp_member_function]().
@ -172,18 +167,18 @@ namespace cppast
cpp_member_function>::basic_member_builder; cpp_member_function>::basic_member_builder;
}; };
private: private:
using cpp_member_function_base::cpp_member_function_base; using cpp_member_function_base::cpp_member_function_base;
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_member_builder<cpp_member_function>; friend basic_member_builder<cpp_member_function>;
}; };
/// A [cppast::cpp_entity]() modelling a C++ conversion operator. /// A [cppast::cpp_entity]() modelling a C++ conversion operator.
class cpp_conversion_op final : public cpp_member_function_base class cpp_conversion_op final : public cpp_member_function_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_conversion_op](). /// Builder for [cppast::cpp_conversion_op]().
@ -209,23 +204,22 @@ namespace cppast
return explicit_; return explicit_;
} }
private: private:
cpp_conversion_op(std::string name, std::unique_ptr<cpp_type> return_t) 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_member_function_base(std::move(name), std::move(return_t)), explicit_(false)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
bool explicit_; bool explicit_;
friend basic_member_builder<cpp_conversion_op>; friend basic_member_builder<cpp_conversion_op>;
}; };
/// A [cppast::cpp_entity]() modelling a C++ constructor. /// A [cppast::cpp_entity]() modelling a C++ constructor.
class cpp_constructor final : public cpp_function_base class cpp_constructor final : public cpp_function_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_constructor](). /// Builder for [cppast::cpp_constructor]().
@ -259,11 +253,10 @@ namespace cppast
return constexpr_; return constexpr_;
} }
private: private:
cpp_constructor(std::string name) cpp_constructor(std::string name)
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false) : cpp_function_base(std::move(name)), explicit_(false), constexpr_(false)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
@ -271,12 +264,12 @@ namespace cppast
bool constexpr_; bool constexpr_;
friend basic_builder<cpp_constructor>; friend basic_builder<cpp_constructor>;
}; };
/// A [cppast::cpp_entity]() modelling a C++ destructor. /// A [cppast::cpp_entity]() modelling a C++ destructor.
class cpp_destructor final : public cpp_function_base class cpp_destructor final : public cpp_function_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_destructor](). /// Builds a [cppast::cpp_destructor]().
@ -308,7 +301,7 @@ namespace cppast
return virtual_; return virtual_;
} }
private: private:
cpp_destructor(std::string name) : cpp_function_base(std::move(name)) {} cpp_destructor(std::string name) : cpp_function_base(std::move(name)) {}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
@ -316,7 +309,7 @@ namespace cppast
cpp_virtual virtual_; cpp_virtual virtual_;
friend basic_builder<cpp_destructor>; friend basic_builder<cpp_destructor>;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED #endif // CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED

View file

@ -10,53 +10,51 @@
namespace cppast namespace cppast
{ {
/// Base class for all kinds of member variables. /// Base class for all kinds of member variables.
class cpp_member_variable_base : public cpp_entity, public cpp_variable_base class cpp_member_variable_base : public cpp_entity, public cpp_variable_base
{ {
public: public:
/// \returns Whether or not the member variable is declared `mutable`. /// \returns Whether or not the member variable is declared `mutable`.
bool is_mutable() const noexcept bool is_mutable() const noexcept
{ {
return mutable_; return mutable_;
} }
protected: protected:
cpp_member_variable_base(std::string name, std::unique_ptr<cpp_type> type, cpp_member_variable_base(std::string name, std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_expression> def, bool is_mutable) std::unique_ptr<cpp_expression> def, bool is_mutable)
: cpp_entity(std::move(name)), : cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def)),
cpp_variable_base(std::move(type), std::move(def)),
mutable_(is_mutable) mutable_(is_mutable)
{ {}
}
private: private:
bool mutable_; bool mutable_;
}; };
/// A [cppast::cpp_entity]() modelling a C++ member variable. /// A [cppast::cpp_entity]() modelling a C++ member variable.
class cpp_member_variable final : public cpp_member_variable_base class cpp_member_variable final : public cpp_member_variable_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered member variable. /// \returns A newly created and registered member variable.
/// \notes `def` may be `nullptr` in which case there is no member initializer provided. /// \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, static std::unique_ptr<cpp_member_variable> build(const cpp_entity_index& idx, cpp_entity_id id,
cpp_entity_id id, std::string name, std::string name,
std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_expression> def, std::unique_ptr<cpp_expression> def,
bool is_mutable); bool is_mutable);
private: private:
using cpp_member_variable_base::cpp_member_variable_base; 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. /// A [cppast::cpp_entity]() modelling a C++ bitfield.
class cpp_bitfield final : public cpp_member_variable_base class cpp_bitfield final : public cpp_member_variable_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered bitfield. /// \returns A newly created and registered bitfield.
@ -76,18 +74,17 @@ namespace cppast
return bits_; return bits_;
} }
private: private:
cpp_bitfield(std::string name, std::unique_ptr<cpp_type> type, unsigned no_bits, cpp_bitfield(std::string name, std::unique_ptr<cpp_type> type, unsigned no_bits,
bool is_mutable) bool is_mutable)
: cpp_member_variable_base(std::move(name), std::move(type), nullptr, is_mutable), : cpp_member_variable_base(std::move(name), std::move(type), nullptr, is_mutable),
bits_(no_bits) bits_(no_bits)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
unsigned bits_; unsigned bits_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED #endif // CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED

View file

@ -7,16 +7,16 @@
#include <cppast/cpp_entity_container.hpp> #include <cppast/cpp_entity_container.hpp>
#include <cppast/cpp_entity_index.hpp> #include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity_ref.hpp>
#include <cppast/cpp_entity_kind.hpp> #include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_entity_ref.hpp>
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a namespace. /// A [cppast::cpp_entity]() modelling a namespace.
class cpp_namespace final : public cpp_entity, class cpp_namespace final : public cpp_entity,
public cpp_entity_container<cpp_namespace, cpp_entity> public cpp_entity_container<cpp_namespace, cpp_entity>
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_namespace](). /// Builds a [cppast::cpp_namespace]().
@ -26,8 +26,7 @@ namespace cppast
/// \effects Sets the namespace name and whether it is inline and nested. /// \effects Sets the namespace name and whether it is inline and nested.
explicit builder(std::string name, bool is_inline, bool is_nested) explicit builder(std::string name, bool is_inline, bool is_nested)
: namespace_(new cpp_namespace(std::move(name), is_inline, is_nested)) : namespace_(new cpp_namespace(std::move(name), is_inline, is_nested))
{ {}
}
/// \effects Adds an entity. /// \effects Adds an entity.
void add_child(std::unique_ptr<cpp_entity> child) noexcept void add_child(std::unique_ptr<cpp_entity> child) noexcept
@ -72,11 +71,10 @@ namespace cppast
return name().empty(); return name().empty();
} }
private: private:
cpp_namespace(std::string name, bool is_inline, bool is_nested) cpp_namespace(std::string name, bool is_inline, bool is_nested)
: cpp_entity(std::move(name)), inline_(is_inline), nested_(is_nested) : cpp_entity(std::move(name)), inline_(is_inline), nested_(is_nested)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
@ -87,31 +85,29 @@ namespace cppast
bool inline_; bool inline_;
bool nested_; bool nested_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_namespace_ref_predicate struct cpp_namespace_ref_predicate
{ {
bool operator()(const cpp_entity& e); bool operator()(const cpp_entity& e);
}; };
} // namespace detail } // namespace detail
/// A reference to a [cppast::cpp_namespace](). /// A reference to a [cppast::cpp_namespace]().
using cpp_namespace_ref = using cpp_namespace_ref = basic_cpp_entity_ref<cpp_namespace, detail::cpp_namespace_ref_predicate>;
basic_cpp_entity_ref<cpp_namespace, detail::cpp_namespace_ref_predicate>;
/// A [cppast::cpp_entity]() modelling a namespace alias. /// A [cppast::cpp_entity]() modelling a namespace alias.
class cpp_namespace_alias final : public cpp_entity class cpp_namespace_alias final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered namespace alias. /// \returns A newly created and registered namespace alias.
static std::unique_ptr<cpp_namespace_alias> build(const cpp_entity_index& idx, static std::unique_ptr<cpp_namespace_alias> build(const cpp_entity_index& idx, cpp_entity_id id,
cpp_entity_id id, std::string name, std::string name, cpp_namespace_ref target);
cpp_namespace_ref target);
/// \returns The [cppast::cpp_namespace_ref]() to the aliased namespace. /// \returns The [cppast::cpp_namespace_ref]() to the aliased namespace.
/// \notes If the namespace aliases aliases another namespace alias, /// \notes If the namespace aliases aliases another namespace alias,
@ -121,24 +117,23 @@ namespace cppast
return target_; return target_;
} }
private: private:
cpp_namespace_alias(std::string name, cpp_namespace_ref target) cpp_namespace_alias(std::string name, cpp_namespace_ref target)
: cpp_entity(std::move(name)), target_(std::move(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;
cpp_namespace_ref target_; cpp_namespace_ref target_;
}; };
/// A [cppast::cpp_entity]() modelling a using directive. /// A [cppast::cpp_entity]() modelling a using directive.
/// ///
/// A using directive is `using namespace std`, for example. /// A using directive is `using namespace std`, for example.
/// \notes It does not have a name. /// \notes It does not have a name.
class cpp_using_directive final : public cpp_entity class cpp_using_directive final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created using directive. /// \returns A newly created using directive.
@ -155,23 +150,21 @@ namespace cppast
return target_; return target_;
} }
private: private:
cpp_using_directive(cpp_namespace_ref target) : cpp_entity(""), target_(std::move(target)) cpp_using_directive(cpp_namespace_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_namespace_ref target_;
}; };
/// A [cppast::cpp_entity]() modelling a using declaration. /// A [cppast::cpp_entity]() modelling a using declaration.
/// ///
/// A using declaration is `using std::vector`, for example. /// A using declaration is `using std::vector`, for example.
/// \notes It does not have a name. /// \notes It does not have a name.
class cpp_using_declaration final : public cpp_entity class cpp_using_declaration final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created using declaration. /// \returns A newly created using declaration.
@ -179,8 +172,7 @@ namespace cppast
/// as nothing can refer to it. /// as nothing can refer to it.
static std::unique_ptr<cpp_using_declaration> build(cpp_entity_ref target) static std::unique_ptr<cpp_using_declaration> build(cpp_entity_ref target)
{ {
return std::unique_ptr<cpp_using_declaration>( return std::unique_ptr<cpp_using_declaration>(new cpp_using_declaration(std::move(target)));
new cpp_using_declaration(std::move(target)));
} }
/// \returns The [cppast::cpp_entity_ref]() that is being used. /// \returns The [cppast::cpp_entity_ref]() that is being used.
@ -190,13 +182,13 @@ namespace cppast
return target_; return target_;
} }
private: private:
cpp_using_declaration(cpp_entity_ref target) : cpp_entity(""), target_(std::move(target)) {} 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_entity_ref target_; cpp_entity_ref target_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_NAMESPACE_HPP_INCLUDED #endif // CPPAST_CPP_NAMESPACE_HPP_INCLUDED

View file

@ -12,29 +12,30 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a macro parameter. /// A [cppast::cpp_entity]() modelling a macro parameter.
class cpp_macro_parameter final : public cpp_entity class cpp_macro_parameter final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly built macro parameter. /// \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. /// \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) 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))); return std::unique_ptr<cpp_macro_parameter>(new cpp_macro_parameter(std::move(name)));
} }
private: private:
cpp_macro_parameter(std::string name) : cpp_entity(std::move(name)) {} cpp_macro_parameter(std::string name) : cpp_entity(std::move(name)) {}
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 macro definition. /// A [cppast::cpp_entity]() modelling a macro definition.
class cpp_macro_definition final : public cpp_entity class cpp_macro_definition final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly built object like macro. /// \returns A newly built object like macro.
@ -53,8 +54,7 @@ namespace cppast
{ {
public: public:
/// \effects Sets the name of the function like macro. /// \effects Sets the name of the function like macro.
function_like_builder(std::string name) function_like_builder(std::string name) : result_(new cpp_macro_definition(std::move(name)))
: result_(new cpp_macro_definition(std::move(name)))
{ {
result_->kind_ = function_like; result_->kind_ = function_like;
} }
@ -126,7 +126,7 @@ namespace cppast
return type_safe::ref(parameters_); return type_safe::ref(parameters_);
} }
private: private:
cpp_entity_kind do_get_entity_kind() const noexcept override; 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_macro_definition(std::string name) : cpp_entity(std::move(name)), kind_(object_like) {}
@ -142,19 +142,19 @@ namespace cppast
} kind_; } kind_;
friend function_like_builder; friend function_like_builder;
}; };
/// The kind of [cppast::cpp_include_directive](). /// The kind of [cppast::cpp_include_directive]().
enum class cpp_include_kind enum class cpp_include_kind
{ {
system, //< An `#include <...>`. system, //< An `#include <...>`.
local, //< An `#include "..."`. local, //< An `#include "..."`.
}; };
/// A [cppast::cpp_entity]() modelling an `#include`. /// A [cppast::cpp_entity]() modelling an `#include`.
class cpp_include_directive final : public cpp_entity class cpp_include_directive final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly built include directive. /// \returns A newly built include directive.
@ -186,14 +186,11 @@ namespace cppast
return full_path_; return full_path_;
} }
private: private:
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind, cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind, std::string full_path)
std::string full_path) : cpp_entity(target.name()), target_(target.id()[0u]), kind_(kind),
: cpp_entity(target.name()),
target_(target.id()[0u]),
kind_(kind),
full_path_(std::move(full_path)) full_path_(std::move(full_path))
{ {
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{}); DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
@ -202,7 +199,7 @@ namespace cppast
cpp_entity_id target_; cpp_entity_id target_;
cpp_include_kind kind_; cpp_include_kind kind_;
std::string full_path_; std::string full_path_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_PREPROCESSOR_HPP_INCLUDED #endif // CPPAST_CPP_PREPROCESSOR_HPP_INCLUDED

View file

@ -10,9 +10,9 @@
namespace cppast namespace cppast
{ {
class cpp_static_assert : public cpp_entity class cpp_static_assert : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created `static_assert()` entity. /// \returns A newly created `static_assert()` entity.
@ -36,17 +36,16 @@ namespace cppast
return msg_; return msg_;
} }
private: private:
cpp_static_assert(std::unique_ptr<cpp_expression> expr, std::string msg) cpp_static_assert(std::unique_ptr<cpp_expression> expr, std::string msg)
: cpp_entity(""), expr_(std::move(expr)), msg_(std::move(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::unique_ptr<cpp_expression> expr_;
std::string msg_; std::string msg_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_STATIC_ASSERT_HPP_INCLUDED #endif // CPPAST_CPP_STATIC_ASSERT_HPP_INCLUDED

View file

@ -7,49 +7,47 @@
namespace cppast namespace cppast
{ {
/// C++ storage class specifiers. /// C++ storage class specifiers.
/// ///
/// See http://en.cppreference.com/w/cpp/language/storage_duration, for example. /// 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, /// \notes These are just all the possible *keywords* used in a variable declaration,
/// not necessarily their *semantic* meaning. /// not necessarily their *semantic* meaning.
enum cpp_storage_class_specifiers : int enum cpp_storage_class_specifiers : int
{ {
cpp_storage_class_none = 0, //< no storage class specifier given. 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 = cpp_storage_class_static = 2, //< *static* or *thread* storage duration and *internal* linkage.
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_extern =
4, //< *static* or *thread* storage duration and *external* linkage.
cpp_storage_class_thread_local = 8, //< *thread* storage duration. cpp_storage_class_thread_local = 8, //< *thread* storage duration.
/// \notes This is the only one that can be combined with the others. /// \notes This is the only one that can be combined with the others.
}; };
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `thread_local`. /// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `thread_local`.
inline bool is_thread_local(cpp_storage_class_specifiers spec) noexcept inline bool is_thread_local(cpp_storage_class_specifiers spec) noexcept
{ {
return (spec & cpp_storage_class_thread_local) != 0; return (spec & cpp_storage_class_thread_local) != 0;
} }
/// \returns Whether the [cppast::cpp_storage_class_speicifers]() contain `auto`. /// \returns Whether the [cppast::cpp_storage_class_speicifers]() contain `auto`.
inline bool is_auto(cpp_storage_class_specifiers spec) noexcept inline bool is_auto(cpp_storage_class_specifiers spec) noexcept
{ {
return (spec & cpp_storage_class_auto) != 0; return (spec & cpp_storage_class_auto) != 0;
} }
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `static`. /// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `static`.
inline bool is_static(cpp_storage_class_specifiers spec) noexcept inline bool is_static(cpp_storage_class_specifiers spec) noexcept
{ {
return (spec & cpp_storage_class_static) != 0; return (spec & cpp_storage_class_static) != 0;
} }
/// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `extern`. /// \returns Whether the [cppast::cpp_storage_class_specifiers]() contain `extern`.
inline bool is_extern(cpp_storage_class_specifiers spec) noexcept inline bool is_extern(cpp_storage_class_specifiers spec) noexcept
{ {
return (spec & cpp_storage_class_extern) != 0; return (spec & cpp_storage_class_extern) != 0;
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_STORAGE_CLASS_SPECIFIERS_HPP_INCLUDED #endif // CPPAST_CPP_STORAGE_CLASS_SPECIFIERS_HPP_INCLUDED

View file

@ -11,25 +11,25 @@
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_container.hpp> #include <cppast/cpp_entity_container.hpp>
#include <cppast/cpp_token.hpp>
#include <cppast/cpp_template_parameter.hpp> #include <cppast/cpp_template_parameter.hpp>
#include <cppast/cpp_token.hpp>
namespace cppast 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. /// 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> class cpp_template : public cpp_entity, public cpp_entity_container<cpp_template, cpp_entity>
{ {
public: public:
/// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities. /// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]()
/// \notes These may be empty for a full specialization. /// entities. \notes These may be empty for a full specialization.
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
{ {
return type_safe::ref(parameters_); return type_safe::ref(parameters_);
} }
protected: protected:
/// Builder class for templates. /// Builder class for templates.
/// ///
/// Inherit from it to provide additional setter. /// Inherit from it to provide additional setter.
@ -38,9 +38,7 @@ namespace cppast
{ {
public: public:
/// \effects Sets the entity that is begin templated. /// \effects Sets the entity that is begin templated.
basic_builder(std::unique_ptr<EntityT> templ) : template_entity(new T(std::move(templ))) basic_builder(std::unique_ptr<EntityT> templ) : template_entity(new T(std::move(templ))) {}
{
}
basic_builder(basic_builder&&) = default; basic_builder(basic_builder&&) = default;
@ -59,14 +57,12 @@ namespace cppast
/// \effects Registers the template. /// \effects Registers the template.
/// \returns The finished template. /// \returns The finished template.
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id, std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id, bool is_definition)
bool is_definition)
{ {
if (is_definition) if (is_definition)
idx.register_definition(std::move(id), type_safe::cref(*template_entity)); idx.register_definition(std::move(id), type_safe::cref(*template_entity));
else else
idx.register_forward_declaration(std::move(id), idx.register_forward_declaration(std::move(id), type_safe::cref(*template_entity));
type_safe::cref(*template_entity));
return std::move(template_entity); return std::move(template_entity);
} }
@ -83,21 +79,21 @@ namespace cppast
add_child(std::move(entity)); add_child(std::move(entity));
} }
private: private:
type_safe::optional<cppast::cpp_scope_name> do_get_scope_name() const override type_safe::optional<cppast::cpp_scope_name> do_get_scope_name() const override
{ {
return begin()->scope_name() ? return begin()->scope_name()
type_safe::make_optional(cppast::cpp_scope_name(type_safe::ref(*this))) : ? type_safe::make_optional(cppast::cpp_scope_name(type_safe::ref(*this)))
type_safe::nullopt; : type_safe::nullopt;
} }
detail::intrusive_list<cpp_template_parameter> parameters_; detail::intrusive_list<cpp_template_parameter> parameters_;
}; };
/// A [cppast::cpp_type]() representing an instantiation of a [cppast::cpp_template](). /// A [cppast::cpp_type]() representing an instantiation of a [cppast::cpp_template]().
class cpp_template_instantiation_type final : public cpp_type class cpp_template_instantiation_type final : public cpp_type
{ {
public: public:
/// Builds a [cppast::cpp_template_instantiation](). /// Builds a [cppast::cpp_template_instantiation]().
class builder class builder
{ {
@ -105,15 +101,13 @@ namespace cppast
/// \effects Sets the primary template being instantiated. /// \effects Sets the primary template being instantiated.
builder(cpp_template_ref templ) builder(cpp_template_ref templ)
: result_(new cpp_template_instantiation_type(std::move(templ))) : result_(new cpp_template_instantiation_type(std::move(templ)))
{ {}
}
/// \effects Adds the next argument. /// \effects Adds the next argument.
/// \requires No call to `add_unexposed_arguments()` has happened before. /// \requires No call to `add_unexposed_arguments()` has happened before.
void add_argument(cpp_template_argument arg) void add_argument(cpp_template_argument arg)
{ {
result_->arguments_ result_->arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
.value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
.push_back(std::move(arg)); .push_back(std::move(arg));
} }
@ -144,8 +138,7 @@ namespace cppast
/// \returns Whether or not the arguments are exposed. /// \returns Whether or not the arguments are exposed.
bool arguments_exposed() const noexcept bool arguments_exposed() const noexcept
{ {
return arguments_.has_value( return arguments_.has_value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
type_safe::variant_type<std::vector<cpp_template_argument>>{});
} }
/// \returns An array ref to the [cppast::cpp_template_argument](), if there are any. /// \returns An array ref to the [cppast::cpp_template_argument](), if there are any.
@ -153,8 +146,7 @@ namespace cppast
type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments() const type_safe::optional<type_safe::array_ref<const cpp_template_argument>> arguments() const
noexcept noexcept
{ {
auto& vec = auto& vec = arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
if (vec.empty()) if (vec.empty())
return type_safe::nullopt; return type_safe::nullopt;
return type_safe::ref(vec.data(), vec.size()); return type_safe::ref(vec.data(), vec.size());
@ -167,12 +159,11 @@ namespace cppast
return arguments_.value(type_safe::variant_type<std::string>{}); return arguments_.value(type_safe::variant_type<std::string>{});
} }
private: private:
cpp_template_instantiation_type(cpp_template_ref ref) cpp_template_instantiation_type(cpp_template_ref ref)
: arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}), : arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
templ_(std::move(ref)) templ_(std::move(ref))
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -181,12 +172,12 @@ namespace cppast
type_safe::variant<std::vector<cpp_template_argument>, std::string> arguments_; type_safe::variant<std::vector<cpp_template_argument>, std::string> arguments_;
cpp_template_ref templ_; cpp_template_ref templ_;
}; };
/// Base class for all entities modelling a C++ template specialization. /// Base class for all entities modelling a C++ template specialization.
class cpp_template_specialization : public cpp_template class cpp_template_specialization : public cpp_template
{ {
public: public:
/// \returns A reference to the template that is being specialized. /// \returns A reference to the template that is being specialized.
cpp_template_ref primary_template() const noexcept cpp_template_ref primary_template() const noexcept
{ {
@ -196,8 +187,7 @@ namespace cppast
/// \returns Whether or not the arguments are exposed. /// \returns Whether or not the arguments are exposed.
bool arguments_exposed() const noexcept bool arguments_exposed() const noexcept
{ {
return arguments_.has_value( return arguments_.has_value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
type_safe::variant_type<std::vector<cpp_template_argument>>{});
} }
/// \returns An iteratable object iterating over the [cppast::cpp_template_argument]()s. /// \returns An iteratable object iterating over the [cppast::cpp_template_argument]()s.
@ -206,8 +196,7 @@ namespace cppast
/// meaning that the arguments are not explictly given but deduced from the signature. /// meaning that the arguments are not explictly given but deduced from the signature.
type_safe::array_ref<const cpp_template_argument> arguments() const noexcept type_safe::array_ref<const cpp_template_argument> arguments() const noexcept
{ {
auto& vec = auto& vec = arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
arguments_.value(type_safe::variant_type<std::vector<cpp_template_argument>>{});
return type_safe::ref(vec.data(), vec.size()); return type_safe::ref(vec.data(), vec.size());
} }
@ -227,7 +216,7 @@ namespace cppast
return parameters().empty(); return parameters().empty();
} }
protected: protected:
/// Builder class for specializations. /// Builder class for specializations.
/// ///
/// Inherit from it to provide additional setter. /// Inherit from it to provide additional setter.
@ -241,12 +230,12 @@ namespace cppast
this->template_entity = std::unique_ptr<T>(new T(std::move(entity), 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. /// \effects Adds the next argument for the [cppast::cpp_template_parameter]() of the
/// \requires No call to `add_unexposed_arguments()` has happened before. /// primary template. \requires No call to `add_unexposed_arguments()` has happened before.
void add_argument(cpp_template_argument arg) void add_argument(cpp_template_argument arg)
{ {
auto& specialization = auto& specialization
static_cast<cpp_template_specialization&>(*this->template_entity); = static_cast<cpp_template_specialization&>(*this->template_entity);
specialization.arguments_ specialization.arguments_
.value(type_safe::variant_type<std::vector<cpp_template_argument>>{}) .value(type_safe::variant_type<std::vector<cpp_template_argument>>{})
.push_back(std::move(arg)); .push_back(std::move(arg));
@ -255,8 +244,8 @@ namespace cppast
/// \effects Adds unexposed arguments as string. /// \effects Adds unexposed arguments as string.
void add_unexposed_arguments(cpp_token_string arg) void add_unexposed_arguments(cpp_token_string arg)
{ {
auto& specialization = auto& specialization
static_cast<cpp_template_specialization&>(*this->template_entity); = static_cast<cpp_template_specialization&>(*this->template_entity);
specialization.arguments_ = std::move(arg); specialization.arguments_ = std::move(arg);
} }
@ -265,8 +254,7 @@ namespace cppast
}; };
/// \effects Sets the entity that is being templated and the primary template. /// \effects Sets the entity that is being templated and the primary template.
cpp_template_specialization(std::unique_ptr<cpp_entity> entity, cpp_template_specialization(std::unique_ptr<cpp_entity> entity, const cpp_template_ref& templ)
const cpp_template_ref& templ)
: cpp_template(std::move(entity)), : cpp_template(std::move(entity)),
arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}), arguments_(type_safe::variant_type<std::vector<cpp_template_argument>>{}),
templ_(templ.id()[0u]) templ_(templ.id()[0u])
@ -276,10 +264,10 @@ namespace cppast
detail::precondition_error_handler{}, "invalid name of template ref"); detail::precondition_error_handler{}, "invalid name of template ref");
} }
private: private:
type_safe::variant<std::vector<cpp_template_argument>, cpp_token_string> arguments_; type_safe::variant<std::vector<cpp_template_argument>, cpp_token_string> arguments_;
cpp_entity_id templ_; cpp_entity_id templ_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_TEMPLATE_HPP_INCLUDED #endif // CPPAST_CPP_TEMPLATE_HPP_INCLUDED

View file

@ -8,54 +8,52 @@
#include <type_safe/optional.hpp> #include <type_safe/optional.hpp>
#include <type_safe/variant.hpp> #include <type_safe/variant.hpp>
#include <cppast/detail/intrusive_list.hpp>
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/cpp_variable_base.hpp> #include <cppast/cpp_variable_base.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast namespace cppast
{ {
/// Base class for all entities modelling a template parameter of some kind. /// Base class for all entities modelling a template parameter of some kind.
class cpp_template_parameter : public cpp_entity class cpp_template_parameter : public cpp_entity
{ {
public: public:
/// \returns Whether or not the parameter is variadic. /// \returns Whether or not the parameter is variadic.
bool is_variadic() const noexcept bool is_variadic() const noexcept
{ {
return variadic_; return variadic_;
} }
protected: protected:
cpp_template_parameter(std::string name, bool variadic) cpp_template_parameter(std::string name, bool variadic)
: cpp_entity(std::move(name)), variadic_(variadic) : cpp_entity(std::move(name)), variadic_(variadic)
{ {}
}
private: private:
bool variadic_; bool variadic_;
}; };
/// The kind of keyword used in a template parameter. /// The kind of keyword used in a template parameter.
enum class cpp_template_keyword enum class cpp_template_keyword
{ {
keyword_class, keyword_class,
keyword_typename keyword_typename
}; };
/// \returns The string associated of the keyword. /// \returns The string associated of the keyword.
const char* to_string(cpp_template_keyword kw) noexcept; const char* to_string(cpp_template_keyword kw) noexcept;
/// A [cppast::cpp_entity]() modelling a C++ template type parameter. /// A [cppast::cpp_entity]() modelling a C++ template type parameter.
class cpp_template_type_parameter final : public cpp_template_parameter class cpp_template_type_parameter final : public cpp_template_parameter
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered template type parameter. /// \returns A newly created and registered template type parameter.
/// \notes The `default_type` may be `nullptr` in which case the parameter has no default. /// \notes The `default_type` may be `nullptr` in which case the parameter has no default.
static std::unique_ptr<cpp_template_type_parameter> build( static std::unique_ptr<cpp_template_type_parameter> build(
const cpp_entity_index& idx, cpp_entity_id id, std::string name, const cpp_entity_index& idx, cpp_entity_id id, std::string name, cpp_template_keyword kw,
cpp_template_keyword kw, bool variadic, bool variadic, std::unique_ptr<cpp_type> default_type = nullptr);
std::unique_ptr<cpp_type> default_type = nullptr);
/// \returns A [ts::optional_ref]() to the default type. /// \returns A [ts::optional_ref]() to the default type.
type_safe::optional_ref<const cpp_type> default_type() const noexcept type_safe::optional_ref<const cpp_type> default_type() const noexcept
@ -69,39 +67,37 @@ namespace cppast
return keyword_; return keyword_;
} }
private: private:
cpp_template_type_parameter(std::string name, cpp_template_keyword kw, bool variadic, cpp_template_type_parameter(std::string name, cpp_template_keyword kw, bool variadic,
std::unique_ptr<cpp_type> default_type) std::unique_ptr<cpp_type> default_type)
: cpp_template_parameter(std::move(name), variadic), : cpp_template_parameter(std::move(name), variadic), default_type_(std::move(default_type)),
default_type_(std::move(default_type)),
keyword_(kw) keyword_(kw)
{ {}
}
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> default_type_; std::unique_ptr<cpp_type> default_type_;
cpp_template_keyword keyword_; cpp_template_keyword keyword_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_template_parameter_ref_predicate struct cpp_template_parameter_ref_predicate
{ {
bool operator()(const cpp_entity& e); bool operator()(const cpp_entity& e);
}; };
} // namespace detail } // namespace detail
/// Reference to a [cppast::cpp_template_type_parameter](). /// Reference to a [cppast::cpp_template_type_parameter]().
using cpp_template_type_parameter_ref = using cpp_template_type_parameter_ref
basic_cpp_entity_ref<cpp_template_type_parameter, = basic_cpp_entity_ref<cpp_template_type_parameter,
detail::cpp_template_parameter_ref_predicate>; detail::cpp_template_parameter_ref_predicate>;
/// A [cppast::cpp_type]() defined by a [cppast::cpp_template_type_parameter](). /// A [cppast::cpp_type]() defined by a [cppast::cpp_template_type_parameter]().
class cpp_template_parameter_type final : public cpp_type class cpp_template_parameter_type final : public cpp_type
{ {
public: public:
/// \returns A newly created parameter type. /// \returns A newly created parameter type.
static std::unique_ptr<cpp_template_parameter_type> build( static std::unique_ptr<cpp_template_parameter_type> build(
cpp_template_type_parameter_ref parameter) cpp_template_type_parameter_ref parameter)
@ -116,11 +112,10 @@ namespace cppast
return parameter_; return parameter_;
} }
private: private:
cpp_template_parameter_type(cpp_template_type_parameter_ref parameter) cpp_template_parameter_type(cpp_template_type_parameter_ref parameter)
: parameter_(std::move(parameter)) : parameter_(std::move(parameter))
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -128,13 +123,13 @@ namespace cppast
} }
cpp_template_type_parameter_ref parameter_; cpp_template_type_parameter_ref parameter_;
}; };
/// A [cppast::cpp_entity]() modelling a C++ non-type template parameter. /// A [cppast::cpp_entity]() modelling a C++ non-type template parameter.
class cpp_non_type_template_parameter final : public cpp_template_parameter, class cpp_non_type_template_parameter final : public cpp_template_parameter,
public cpp_variable_base public cpp_variable_base
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered non type template parameter. /// \returns A newly created and registered non type template parameter.
@ -144,35 +139,34 @@ namespace cppast
std::unique_ptr<cpp_type> type, bool is_variadic, std::unique_ptr<cpp_type> type, bool is_variadic,
std::unique_ptr<cpp_expression> default_value = nullptr); std::unique_ptr<cpp_expression> default_value = nullptr);
private: private:
cpp_non_type_template_parameter(std::string name, std::unique_ptr<cpp_type> type, cpp_non_type_template_parameter(std::string name, std::unique_ptr<cpp_type> type, bool variadic,
bool variadic, std::unique_ptr<cpp_expression> def) std::unique_ptr<cpp_expression> def)
: cpp_template_parameter(std::move(name), variadic), : cpp_template_parameter(std::move(name), variadic),
cpp_variable_base(std::move(type), std::move(def)) cpp_variable_base(std::move(type), std::move(def))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_template_ref_predicate struct cpp_template_ref_predicate
{ {
bool operator()(const cpp_entity& e); bool operator()(const cpp_entity& e);
}; };
} // namespace detail } // namespace detail
class cpp_template; class cpp_template;
/// A reference to a [cppast::cpp_template]() or a [cppast::cpp_template_template_parameter](). /// 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>; 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. /// A [cppast::cpp_entity]() modelling a C++ template template parameter.
class cpp_template_template_parameter final : public cpp_template_parameter class cpp_template_template_parameter final : public cpp_template_parameter
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_template_template_parameter](). /// Builds a [cppast::cpp_template_template_parameter]().
@ -182,8 +176,7 @@ namespace cppast
/// \effects Sets the name and whether it is variadic. /// \effects Sets the name and whether it is variadic.
builder(std::string name, bool variadic) builder(std::string name, bool variadic)
: parameter_(new cpp_template_template_parameter(std::move(name), variadic)) : parameter_(new cpp_template_template_parameter(std::move(name), variadic))
{ {}
}
/// \effects Sets the keyword, /// \effects Sets the keyword,
/// default is [cpp_template_keyword::keyword_class](). /// default is [cpp_template_keyword::keyword_class]().
@ -218,7 +211,8 @@ namespace cppast
std::unique_ptr<cpp_template_template_parameter> parameter_; std::unique_ptr<cpp_template_template_parameter> parameter_;
}; };
/// \returns An iteratable object containing the template parameters of the template template parameter. /// \returns An iteratable object containing the template parameters of the template template
/// parameter.
detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept detail::iteratable_intrusive_list<cpp_template_parameter> parameters() const noexcept
{ {
return type_safe::ref(parameters_); return type_safe::ref(parameters_);
@ -236,51 +230,47 @@ namespace cppast
return default_; return default_;
} }
private: private:
cpp_template_template_parameter(std::string name, bool variadic) cpp_template_template_parameter(std::string name, bool variadic)
: cpp_template_parameter(std::move(name), variadic), : cpp_template_parameter(std::move(name), variadic),
keyword_(cpp_template_keyword::keyword_class) keyword_(cpp_template_keyword::keyword_class)
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
detail::intrusive_list<cpp_template_parameter> parameters_; detail::intrusive_list<cpp_template_parameter> parameters_;
type_safe::optional<cpp_template_ref> default_; type_safe::optional<cpp_template_ref> default_;
cpp_template_keyword keyword_; cpp_template_keyword keyword_;
}; };
/// An argument for a [cppast::cpp_template_parameter](). /// 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]()), /// It is based on a [ts::variant]() of [cppast::cpp_type]() (for
/// [cppast::cpp_expression]() (for [cppast::cpp_non_type_template_parameter]()) and [cppast::cpp_template_ref]() /// [cppast::cpp_template_type_parameter]()), [cppast::cpp_expression]() (for
/// (for [cppast::cpp_template_template_parameter](). /// [cppast::cpp_non_type_template_parameter]()) and [cppast::cpp_template_ref]() (for
class cpp_template_argument /// [cppast::cpp_template_template_parameter]().
{ class cpp_template_argument
public: {
public:
/// \effects Initializes it passing a type as argument. /// \effects Initializes it passing a type as argument.
/// This corresponds to a [cppast::cpp_template_type_parameter](). /// 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](). /// \notes This constructor only participates in overload resolution if `T` is dervied from
/// \param 1 /// [cppast::cpp_type](). \param 1 \exclude
/// \exclude
template <typename T, template <typename T,
typename std::enable_if<std::is_base_of<cpp_type, T>::value, int>::type = 0> typename std::enable_if<std::is_base_of<cpp_type, T>::value, int>::type = 0>
cpp_template_argument(std::unique_ptr<T> type) cpp_template_argument(std::unique_ptr<T> type)
: arg_(std::unique_ptr<cpp_type>(std::move(type))) : arg_(std::unique_ptr<cpp_type>(std::move(type)))
{ {}
}
/// \effects Initializes it passing an expression as argument. /// \effects Initializes it passing an expression as argument.
/// This corresponds to a [cppast::cpp_non_type_template_parameter](). /// 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](). /// \notes This constructor only participates in overload resolution if `T` is dervied from
/// \param 1 /// [cppast::cpp_expression](). \param 1 \exclude
/// \exclude template <typename T,
template <typename T, typename = typename std::enable_if< typename = typename std::enable_if<std::is_base_of<cpp_expression, T>::value>::type>
std::is_base_of<cpp_expression, T>::value>::type>
cpp_template_argument(std::unique_ptr<T> expr) cpp_template_argument(std::unique_ptr<T> expr)
: arg_(std::unique_ptr<cpp_expression>(std::move(expr))) : arg_(std::unique_ptr<cpp_expression>(std::move(expr)))
{ {}
}
/// \effects Initializes it passing a template as argument. /// \effects Initializes it passing a template as argument.
/// This corresponds to a [cppast::cpp_template_template_parameter](). /// This corresponds to a [cppast::cpp_template_template_parameter]().
@ -295,9 +285,7 @@ namespace cppast
type_safe::optional_ref<const cpp_expression> expression() const noexcept type_safe::optional_ref<const cpp_expression> expression() const noexcept
{ {
return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_expression>>{}) return arg_.optional_value(type_safe::variant_type<std::unique_ptr<cpp_expression>>{})
.map([](const std::unique_ptr<cpp_expression>& expr) { .map([](const std::unique_ptr<cpp_expression>& expr) { return type_safe::ref(*expr); });
return type_safe::ref(*expr);
});
} }
type_safe::optional_ref<const cpp_template_ref> template_ref() const noexcept type_safe::optional_ref<const cpp_template_ref> template_ref() const noexcept
@ -305,11 +293,10 @@ namespace cppast
return arg_.optional_value(type_safe::variant_type<cpp_template_ref>{}); return arg_.optional_value(type_safe::variant_type<cpp_template_ref>{});
} }
private: private:
type_safe::variant<std::unique_ptr<cpp_type>, std::unique_ptr<cpp_expression>, type_safe::variant<std::unique_ptr<cpp_type>, std::unique_ptr<cpp_expression>, cpp_template_ref>
cpp_template_ref>
arg_; arg_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED #endif // CPPAST_CPP_TEMPLATE_PARAMETER_HPP_INCLUDED

View file

@ -12,9 +12,9 @@
namespace cppast namespace cppast
{ {
/// The kinds of C++ tokens. /// The kinds of C++ tokens.
enum class cpp_token_kind enum class cpp_token_kind
{ {
identifier, //< Any identifier. identifier, //< Any identifier.
keyword, //< Any keyword. keyword, //< Any keyword.
int_literal, //< An integer literal. int_literal, //< An integer literal.
@ -22,18 +22,16 @@ namespace cppast
char_literal, //< A character literal. char_literal, //< A character literal.
string_literal, //< A string literal. string_literal, //< A string literal.
punctuation //< Any other punctuation. punctuation //< Any other punctuation.
}; };
/// A C++ token. /// A C++ token.
struct cpp_token struct cpp_token
{ {
std::string spelling; std::string spelling;
cpp_token_kind kind; cpp_token_kind kind;
cpp_token(cpp_token_kind kind, std::string spelling) cpp_token(cpp_token_kind kind, std::string spelling) : spelling(std::move(spelling)), kind(kind)
: spelling(std::move(spelling)), kind(kind) {}
{
}
friend bool operator==(const cpp_token& lhs, const cpp_token& rhs) noexcept friend bool operator==(const cpp_token& lhs, const cpp_token& rhs) noexcept
{ {
@ -44,12 +42,12 @@ namespace cppast
{ {
return !(rhs == lhs); return !(rhs == lhs);
} }
}; };
/// A combination of multiple C++ tokens. /// A combination of multiple C++ tokens.
class cpp_token_string class cpp_token_string
{ {
public: public:
/// Builds a token string. /// Builds a token string.
class builder class builder
{ {
@ -77,8 +75,8 @@ namespace cppast
/// Tokenizes a string. /// Tokenizes a string.
/// \effects Splits the string into C++ tokens. /// \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). /// The string must contain valid tokens and must already be preprocessed (i.e. translation
/// \returns The tokenized string. /// phase 6 is already done). \returns The tokenized string.
static cpp_token_string tokenize(std::string str); static cpp_token_string tokenize(std::string str);
/// \effects Creates it from a sequence of tokens. /// \effects Creates it from a sequence of tokens.
@ -120,18 +118,18 @@ namespace cppast
/// \returns The string representation of the tokens, without any whitespace. /// \returns The string representation of the tokens, without any whitespace.
std::string as_string() const; std::string as_string() const;
private: private:
std::vector<cpp_token> tokens_; std::vector<cpp_token> tokens_;
friend bool operator==(const cpp_token_string& lhs, const cpp_token_string& rhs); 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); 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) inline bool operator!=(const cpp_token_string& lhs, const cpp_token_string& rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_TOKEN_HPP_INCLUDED #endif // CPPAST_CPP_TOKEN_HPP_INCLUDED

View file

@ -8,15 +8,15 @@
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <cppast/detail/intrusive_list.hpp>
#include <cppast/cpp_entity_ref.hpp>
#include <cppast/code_generator.hpp> #include <cppast/code_generator.hpp>
#include <cppast/cpp_entity_ref.hpp>
#include <cppast/detail/intrusive_list.hpp>
namespace cppast namespace cppast
{ {
/// The kinds of a [cppast::cpp_type](). /// The kinds of a [cppast::cpp_type]().
enum class cpp_type_kind enum class cpp_type_kind
{ {
builtin_t, builtin_t,
user_defined_t, user_defined_t,
@ -39,12 +39,12 @@ namespace cppast
dependent_t, dependent_t,
unexposed_t, unexposed_t,
}; };
/// Base class for all C++ types. /// Base class for all C++ types.
class cpp_type : detail::intrusive_list_node<cpp_type> class cpp_type : detail::intrusive_list_node<cpp_type>
{ {
public: public:
cpp_type(const cpp_type&) = delete; cpp_type(const cpp_type&) = delete;
cpp_type& operator=(const cpp_type&) = delete; cpp_type& operator=(const cpp_type&) = delete;
@ -67,16 +67,17 @@ namespace cppast
/// User data is just some kind of pointer, there are no requirements. /// User data is just some kind of pointer, there are no requirements.
/// The class will do no lifetime management. /// 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. /// 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 void set_user_data(void* data) const noexcept
{ {
user_data_ = data; user_data_ = data;
} }
protected: protected:
cpp_type() noexcept : user_data_(nullptr) {} cpp_type() noexcept : user_data_(nullptr) {}
private: private:
/// \returns The [cppast::cpp_type_kind](). /// \returns The [cppast::cpp_type_kind]().
virtual cpp_type_kind do_get_kind() const noexcept = 0; virtual cpp_type_kind do_get_kind() const noexcept = 0;
@ -87,14 +88,14 @@ namespace cppast
template <typename T> template <typename T>
friend struct detail::intrusive_list_access; friend struct detail::intrusive_list_access;
friend detail::intrusive_list_node<cpp_type>; friend detail::intrusive_list_node<cpp_type>;
}; };
/// An unexposed [cppast::cpp_type](). /// An unexposed [cppast::cpp_type]().
/// ///
/// This is one where no further information besides a name is available. /// This is one where no further information besides a name is available.
class cpp_unexposed_type final : public cpp_type class cpp_unexposed_type final : public cpp_type
{ {
public: public:
/// \returns A newly created unexposed type. /// \returns A newly created unexposed type.
static std::unique_ptr<cpp_unexposed_type> build(std::string name) static std::unique_ptr<cpp_unexposed_type> build(std::string name)
{ {
@ -107,7 +108,7 @@ namespace cppast
return name_; return name_;
} }
private: private:
cpp_unexposed_type(std::string name) : name_(std::move(name)) {} cpp_unexposed_type(std::string name) : name_(std::move(name)) {}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
@ -116,11 +117,11 @@ namespace cppast
} }
std::string name_; std::string name_;
}; };
/// The C++ builtin types. /// The C++ builtin types.
enum cpp_builtin_type_kind enum cpp_builtin_type_kind
{ {
cpp_void, //< `void` cpp_void, //< `void`
cpp_bool, //< `bool` cpp_bool, //< `bool`
@ -150,17 +151,17 @@ namespace cppast
cpp_char32, //< `char32_t` cpp_char32, //< `char32_t`
cpp_nullptr, //< `decltype(nullptr)` aka `std::nullptr_t` cpp_nullptr, //< `decltype(nullptr)` aka `std::nullptr_t`
}; };
/// \returns The string representing the spelling of that type in the source code. /// \returns The string representing the spelling of that type in the source code.
const char* to_string(cpp_builtin_type_kind kind) noexcept; const char* to_string(cpp_builtin_type_kind kind) noexcept;
/// A builtin [cppast::cpp_type](). /// A builtin [cppast::cpp_type]().
/// ///
/// This is one where there is no associated [cppast::cpp_entity](). /// This is one where there is no associated [cppast::cpp_entity]().
class cpp_builtin_type final : public cpp_type class cpp_builtin_type final : public cpp_type
{ {
public: public:
/// \returns A newly created builtin type. /// \returns A newly created builtin type.
static std::unique_ptr<cpp_builtin_type> build(cpp_builtin_type_kind kind) static std::unique_ptr<cpp_builtin_type> build(cpp_builtin_type_kind kind)
{ {
@ -173,7 +174,7 @@ namespace cppast
return kind_; return kind_;
} }
private: private:
cpp_builtin_type(cpp_builtin_type_kind kind) : kind_(kind) {} cpp_builtin_type(cpp_builtin_type_kind kind) : kind_(kind) {}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
@ -182,40 +183,40 @@ namespace cppast
} }
cpp_builtin_type_kind kind_; cpp_builtin_type_kind kind_;
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
struct cpp_type_ref_predicate struct cpp_type_ref_predicate
{ {
bool operator()(const cpp_entity& e); bool operator()(const cpp_entity& e);
}; };
} // namespace detail } // namespace detail
/// Reference to a [cppast::cpp_entity]() representing a new type. /// 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>; using cpp_type_ref = basic_cpp_entity_ref<cpp_entity, detail::cpp_type_ref_predicate>;
/// A user-defined [cppast::cpp_type](). /// A user-defined [cppast::cpp_type]().
/// ///
/// It has an associated [cppast::cpp_entity](). /// It has an associated [cppast::cpp_entity]().
class cpp_user_defined_type final : public cpp_type class cpp_user_defined_type final : public cpp_type
{ {
public: public:
/// \returns A newly created user-defined type. /// \returns A newly created user-defined type.
static std::unique_ptr<cpp_user_defined_type> build(cpp_type_ref entity) static std::unique_ptr<cpp_user_defined_type> build(cpp_type_ref entity)
{ {
return std::unique_ptr<cpp_user_defined_type>( return std::unique_ptr<cpp_user_defined_type>(new cpp_user_defined_type(std::move(entity)));
new cpp_user_defined_type(std::move(entity)));
} }
/// \returns A [cppast::cpp_type_ref]() to the associated [cppast::cpp_entity]() that is the type. /// \returns A [cppast::cpp_type_ref]() to the associated [cppast::cpp_entity]() that is the
/// type.
const cpp_type_ref& entity() const noexcept const cpp_type_ref& entity() const noexcept
{ {
return entity_; return entity_;
} }
private: private:
cpp_user_defined_type(cpp_type_ref entity) : entity_(std::move(entity)) {} cpp_user_defined_type(cpp_type_ref entity) : entity_(std::move(entity)) {}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
@ -224,34 +225,34 @@ namespace cppast
} }
cpp_type_ref entity_; cpp_type_ref entity_;
}; };
/// A [cppast::cpp_type]() that isn't given but deduced by `auto`. /// A [cppast::cpp_type]() that isn't given but deduced by `auto`.
class cpp_auto_type final : public cpp_type class cpp_auto_type final : public cpp_type
{ {
public: public:
/// \returns A newly created `auto` type. /// \returns A newly created `auto` type.
static std::unique_ptr<cpp_auto_type> build() static std::unique_ptr<cpp_auto_type> build()
{ {
return std::unique_ptr<cpp_auto_type>(new cpp_auto_type); return std::unique_ptr<cpp_auto_type>(new cpp_auto_type);
} }
private: private:
cpp_auto_type() = default; cpp_auto_type() = default;
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
return cpp_type_kind::auto_t; return cpp_type_kind::auto_t;
} }
}; };
class cpp_template_parameter_type; class cpp_template_parameter_type;
class cpp_template_instantiation_type; class cpp_template_instantiation_type;
/// A [cppast::cpp_type]() that depends on another type. /// A [cppast::cpp_type]() that depends on another type.
class cpp_dependent_type final : public cpp_type class cpp_dependent_type final : public cpp_type
{ {
public: public:
/// \returns A newly created type dependent on a [cppast::cpp_template_parameter_type](). /// \returns A newly created type dependent on a [cppast::cpp_template_parameter_type]().
static std::unique_ptr<cpp_dependent_type> build( static std::unique_ptr<cpp_dependent_type> build(
std::string name, std::unique_ptr<cpp_template_parameter_type> dependee); std::string name, std::unique_ptr<cpp_template_parameter_type> dependee);
@ -268,17 +269,17 @@ namespace cppast
} }
/// \returns A reference to the [cppast::cpp_type]() it depends one. /// \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](). /// \notes This is either [cppast::cpp_template_parameter_type]() or
/// [cppast:cpp_template_instantiation_type]().
const cpp_type& dependee() const noexcept const cpp_type& dependee() const noexcept
{ {
return *dependee_; return *dependee_;
} }
private: private:
cpp_dependent_type(std::string name, std::unique_ptr<cpp_type> dependee) cpp_dependent_type(std::string name, std::unique_ptr<cpp_type> dependee)
: name_(std::move(name)), dependee_(std::move(dependee)) : name_(std::move(name)), dependee_(std::move(dependee))
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -287,37 +288,36 @@ namespace cppast
std::string name_; std::string name_;
std::unique_ptr<cpp_type> dependee_; std::unique_ptr<cpp_type> dependee_;
}; };
/// The kinds of C++ cv qualifiers. /// The kinds of C++ cv qualifiers.
enum cpp_cv enum cpp_cv
{ {
cpp_cv_none, cpp_cv_none,
cpp_cv_const, cpp_cv_const,
cpp_cv_volatile, cpp_cv_volatile,
cpp_cv_const_volatile, cpp_cv_const_volatile,
}; };
/// \returns `true` if the qualifier contains `const`. /// \returns `true` if the qualifier contains `const`.
inline bool is_const(cpp_cv cv) noexcept inline bool is_const(cpp_cv cv) noexcept
{ {
return cv == cpp_cv_const || cv == cpp_cv_const_volatile; return cv == cpp_cv_const || cv == cpp_cv_const_volatile;
} }
/// \returns `true` if the qualifier contains `volatile`. /// \returns `true` if the qualifier contains `volatile`.
inline bool is_volatile(cpp_cv cv) noexcept inline bool is_volatile(cpp_cv cv) noexcept
{ {
return cv == cpp_cv_volatile || cv == cpp_cv_const_volatile; return cv == cpp_cv_volatile || cv == cpp_cv_const_volatile;
} }
/// A [cppast::cpp_cv]() qualified [cppast::cpp_type](). /// A [cppast::cpp_cv]() qualified [cppast::cpp_type]().
class cpp_cv_qualified_type final : public cpp_type class cpp_cv_qualified_type final : public cpp_type
{ {
public: public:
/// \returns A newly created qualified type. /// \returns A newly created qualified type.
/// \requires `cv` must not be [cppast::cpp_cv::cpp_cv_none](). /// \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, static std::unique_ptr<cpp_cv_qualified_type> build(std::unique_ptr<cpp_type> type, cpp_cv cv)
cpp_cv cv)
{ {
DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{}); DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{});
return std::unique_ptr<cpp_cv_qualified_type>( return std::unique_ptr<cpp_cv_qualified_type>(
@ -336,11 +336,10 @@ namespace cppast
return cv_; return cv_;
} }
private: private:
cpp_cv_qualified_type(std::unique_ptr<cpp_type> type, cpp_cv cv) cpp_cv_qualified_type(std::unique_ptr<cpp_type> type, cpp_cv cv)
: type_(std::move(type)), cv_(cv) : type_(std::move(type)), cv_(cv)
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -349,21 +348,21 @@ namespace cppast
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
cpp_cv cv_; cpp_cv cv_;
}; };
/// \returns The type without top-level const/volatile qualifiers. /// \returns The type without top-level const/volatile qualifiers.
const cpp_type& remove_cv(const cpp_type& type) noexcept; const cpp_type& remove_cv(const cpp_type& type) noexcept;
/// \returns The type without top-level const qualifiers. /// \returns The type without top-level const qualifiers.
const cpp_type& remove_const(const cpp_type& type) noexcept; const cpp_type& remove_const(const cpp_type& type) noexcept;
/// \returns The type without top-level volatile qualifiers. /// \returns The type without top-level volatile qualifiers.
const cpp_type& remove_volatile(const cpp_type& type) noexcept; const cpp_type& remove_volatile(const cpp_type& type) noexcept;
/// A pointer to a [cppast::cpp_type](). /// A pointer to a [cppast::cpp_type]().
class cpp_pointer_type final : public cpp_type class cpp_pointer_type final : public cpp_type
{ {
public: public:
/// \returns A newly created pointer type. /// \returns A newly created pointer type.
static std::unique_ptr<cpp_pointer_type> build(std::unique_ptr<cpp_type> pointee) static std::unique_ptr<cpp_pointer_type> build(std::unique_ptr<cpp_type> pointee)
{ {
@ -376,7 +375,7 @@ namespace cppast
return *pointee_; return *pointee_;
} }
private: private:
cpp_pointer_type(std::unique_ptr<cpp_type> pointee) : pointee_(std::move(pointee)) {} cpp_pointer_type(std::unique_ptr<cpp_type> pointee) : pointee_(std::move(pointee)) {}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
@ -385,28 +384,27 @@ namespace cppast
} }
std::unique_ptr<cpp_type> pointee_; std::unique_ptr<cpp_type> pointee_;
}; };
/// The kinds of C++ references. /// The kinds of C++ references.
enum cpp_reference enum cpp_reference
{ {
cpp_ref_none, cpp_ref_none,
cpp_ref_lvalue, cpp_ref_lvalue,
cpp_ref_rvalue, cpp_ref_rvalue,
}; };
/// A reference to a [cppast::cpp_type](). /// A reference to a [cppast::cpp_type]().
class cpp_reference_type final : public cpp_type class cpp_reference_type final : public cpp_type
{ {
public: public:
/// \returns A newly created qualified type. /// \returns A newly created qualified type.
/// \requires `ref` must not be [cppast::cpp_reference::cpp_ref_none](). /// \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, static std::unique_ptr<cpp_reference_type> build(std::unique_ptr<cpp_type> type,
cpp_reference ref) cpp_reference ref)
{ {
DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{}); DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{});
return std::unique_ptr<cpp_reference_type>( return std::unique_ptr<cpp_reference_type>(new cpp_reference_type(std::move(type), ref));
new cpp_reference_type(std::move(type), ref));
} }
/// \returns A reference to the [cppast::cpp_type]() that is referenced. /// \returns A reference to the [cppast::cpp_type]() that is referenced.
@ -421,11 +419,10 @@ namespace cppast
return ref_; return ref_;
} }
private: private:
cpp_reference_type(std::unique_ptr<cpp_type> referee, cpp_reference ref) cpp_reference_type(std::unique_ptr<cpp_type> referee, cpp_reference ref)
: referee_(std::move(referee)), ref_(ref) : referee_(std::move(referee)), ref_(ref)
{ {}
}
cpp_type_kind do_get_kind() const noexcept override cpp_type_kind do_get_kind() const noexcept override
{ {
@ -434,14 +431,14 @@ namespace cppast
std::unique_ptr<cpp_type> referee_; std::unique_ptr<cpp_type> referee_;
cpp_reference ref_; cpp_reference ref_;
}; };
/// \returns The type as a string representation. /// \returns The type as a string representation.
std::string to_string(const cpp_type& type); std::string to_string(const cpp_type& type);
/// \exclude /// \exclude
namespace detail namespace detail
{ {
// whether or not it requires special treatment when printing it // 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 // i.e. function pointer types are complex as the identifier has to be put inside
bool is_complex_type(const cpp_type& type) noexcept; bool is_complex_type(const cpp_type& type) noexcept;
@ -456,7 +453,7 @@ namespace cppast
// write prefix, variadic, name, suffix // write prefix, variadic, name, suffix
void write_type(code_generator::output& output, const cpp_type& type, std::string name, void write_type(code_generator::output& output, const cpp_type& type, std::string name,
bool is_variadic = false); bool is_variadic = false);
} // namespace detail } // namespace detail
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_TYPE_HPP_INCLUDED #endif // CPPAST_CPP_TYPE_HPP_INCLUDED

View file

@ -10,22 +10,20 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a type alias/typedef. /// A [cppast::cpp_entity]() modelling a type alias/typedef.
/// \notes There is no distinction between `using` and `typedef` type aliases made in the AST. /// \notes There is no distinction between `using` and `typedef` type aliases made in the AST.
class cpp_type_alias final : public cpp_entity class cpp_type_alias final : public cpp_entity
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered type alias. /// \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, static std::unique_ptr<cpp_type_alias> build(const cpp_entity_index& idx, cpp_entity_id id,
std::string name, std::string name, std::unique_ptr<cpp_type> type);
std::unique_ptr<cpp_type> type);
/// \returns A newly created type alias that isn't registered. /// \returns A newly created type alias that isn't registered.
/// \notes This function is intendend for templated type aliases. /// \notes This function is intendend for templated type aliases.
static std::unique_ptr<cpp_type_alias> build(std::string name, static std::unique_ptr<cpp_type_alias> build(std::string name, std::unique_ptr<cpp_type> type);
std::unique_ptr<cpp_type> type);
/// \returns A reference to the aliased [cppast::cpp_type](). /// \returns A reference to the aliased [cppast::cpp_type]().
const cpp_type& underlying_type() const noexcept const cpp_type& underlying_type() const noexcept
@ -33,16 +31,15 @@ namespace cppast
return *type_; return *type_;
} }
private: private:
cpp_type_alias(std::string name, std::unique_ptr<cpp_type> type) cpp_type_alias(std::string name, std::unique_ptr<cpp_type> type)
: cpp_entity(std::move(name)), type_(std::move(type)) : cpp_entity(std::move(name)), 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_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_TYPE_ALIAS_HPP_INCLUDED #endif // CPPAST_CPP_TYPE_ALIAS_HPP_INCLUDED

View file

@ -12,15 +12,15 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a C++ variable. /// A [cppast::cpp_entity]() modelling a C++ variable.
/// \notes This is not a member variable, /// \notes This is not a member variable,
/// use [cppast::cpp_member_variable]() for that. /// use [cppast::cpp_member_variable]() for that.
/// But it can be `static` member variable. /// But it can be `static` member variable.
class cpp_variable final : public cpp_entity, class cpp_variable final : public cpp_entity,
public cpp_variable_base, public cpp_variable_base,
public cpp_forward_declarable public cpp_forward_declarable
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// \returns A newly created and registered variable. /// \returns A newly created and registered variable.
@ -51,22 +51,19 @@ namespace cppast
return is_constexpr_; return is_constexpr_;
} }
private: private:
cpp_variable(std::string name, std::unique_ptr<cpp_type> type, cpp_variable(std::string name, std::unique_ptr<cpp_type> type,
std::unique_ptr<cpp_expression> def, cpp_storage_class_specifiers spec, std::unique_ptr<cpp_expression> def, cpp_storage_class_specifiers spec,
bool is_constexpr) bool is_constexpr)
: cpp_entity(std::move(name)), : cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def)),
cpp_variable_base(std::move(type), std::move(def)), storage_(spec), is_constexpr_(is_constexpr)
storage_(spec), {}
is_constexpr_(is_constexpr)
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_storage_class_specifiers storage_; cpp_storage_class_specifiers storage_;
bool is_constexpr_; bool is_constexpr_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_VARIABLE_HPP_INCLUDED #endif // CPPAST_CPP_VARIABLE_HPP_INCLUDED

View file

@ -10,13 +10,13 @@
namespace cppast namespace cppast
{ {
/// Additional base class for all [cppast::cpp_entity]() modelling some kind of variable. /// Additional base class for all [cppast::cpp_entity]() modelling some kind of variable.
/// ///
/// Examples are [cppast::cpp_variable]() or [cppast::cpp_function_parameter](), /// Examples are [cppast::cpp_variable]() or [cppast::cpp_function_parameter](),
/// or anything that is name/type/default-value triple. /// or anything that is name/type/default-value triple.
class cpp_variable_base class cpp_variable_base
{ {
public: public:
/// \returns A reference to the [cppast::cpp_type]() of the variable. /// \returns A reference to the [cppast::cpp_type]() of the variable.
const cpp_type& type() const noexcept const cpp_type& type() const noexcept
{ {
@ -29,18 +29,17 @@ namespace cppast
return type_safe::opt_ref(default_.get()); return type_safe::opt_ref(default_.get());
} }
protected: protected:
cpp_variable_base(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def) cpp_variable_base(std::unique_ptr<cpp_type> type, std::unique_ptr<cpp_expression> def)
: type_(std::move(type)), default_(std::move(def)) : type_(std::move(type)), default_(std::move(def))
{ {}
}
~cpp_variable_base() noexcept = default; ~cpp_variable_base() noexcept = default;
private: private:
std::unique_ptr<cpp_type> type_; std::unique_ptr<cpp_type> type_;
std::unique_ptr<cpp_expression> default_; std::unique_ptr<cpp_expression> default_;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_VARIABLE_BASE_HPP_INCLUDED #endif // CPPAST_CPP_VARIABLE_BASE_HPP_INCLUDED

View file

@ -10,10 +10,10 @@
namespace cppast namespace cppast
{ {
/// A [cppast::cpp_entity]() modelling a C++ alias template. /// A [cppast::cpp_entity]() modelling a C++ alias template.
class cpp_variable_template final : public cpp_template class cpp_variable_template final : public cpp_template
{ {
public: public:
static cpp_entity_kind kind() noexcept; static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_variable_template](). /// Builder for [cppast::cpp_variable_template]().
@ -29,16 +29,15 @@ namespace cppast
return static_cast<const cpp_variable&>(*begin()); return static_cast<const cpp_variable&>(*begin());
} }
private: private:
cpp_variable_template(std::unique_ptr<cpp_variable> variable) cpp_variable_template(std::unique_ptr<cpp_variable> variable)
: cpp_template(std::unique_ptr<cpp_entity>(variable.release())) : cpp_template(std::unique_ptr<cpp_entity>(variable.release()))
{ {}
}
cpp_entity_kind do_get_entity_kind() const noexcept override; cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_builder<cpp_variable_template, cpp_variable>; friend basic_builder<cpp_variable_template, cpp_variable>;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_CPP_VARIABLE_TEMPLATE_HPP_INCLUDED #endif // CPPAST_CPP_VARIABLE_TEMPLATE_HPP_INCLUDED

View file

@ -8,31 +8,29 @@
#include <debug_assert.hpp> #include <debug_assert.hpp>
#ifdef CPPAST_ENABLE_ASSERTIONS #ifdef CPPAST_ENABLE_ASSERTIONS
#define CPPAST_ASSERTION_LEVEL 1 # define CPPAST_ASSERTION_LEVEL 1
#else #else
#define CPPAST_ASSERTION_LEVEL 0 # define CPPAST_ASSERTION_LEVEL 0
#endif #endif
#ifdef CPPAST_ENABLE_PRECONDITION_CHECKS #ifdef CPPAST_ENABLE_PRECONDITION_CHECKS
#define CPPAST_PRECONDITION_LEVEL 1 # define CPPAST_PRECONDITION_LEVEL 1
#else #else
#define CPPAST_PRECONDITION_LEVEL 0 # define CPPAST_PRECONDITION_LEVEL 0
#endif #endif
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
struct assert_handler : debug_assert::set_level<CPPAST_ASSERTION_LEVEL>, struct assert_handler : debug_assert::set_level<CPPAST_ASSERTION_LEVEL>,
debug_assert::default_handler debug_assert::default_handler
{ {};
};
struct precondition_error_handler : debug_assert::set_level<CPPAST_PRECONDITION_LEVEL>, struct precondition_error_handler : debug_assert::set_level<CPPAST_PRECONDITION_LEVEL>,
debug_assert::default_handler debug_assert::default_handler
{ {};
}; } // namespace detail
} } // namespace cppast
} // namespace cppast::detail
#endif // CPPAST_ASSERT_HPP_INCLUDED #endif // CPPAST_ASSERT_HPP_INCLUDED

View file

@ -5,8 +5,8 @@
#ifndef CPPAST_INTRUSIVE_LIST_HPP_INCLUDED #ifndef CPPAST_INTRUSIVE_LIST_HPP_INCLUDED
#define CPPAST_INTRUSIVE_LIST_HPP_INCLUDED #define CPPAST_INTRUSIVE_LIST_HPP_INCLUDED
#include <memory>
#include <iterator> #include <iterator>
#include <memory>
#include <type_safe/optional_ref.hpp> #include <type_safe/optional_ref.hpp>
@ -14,10 +14,10 @@
namespace cppast namespace cppast
{ {
class cpp_file; class cpp_file;
namespace detail namespace detail
{ {
template <typename T> template <typename T>
class intrusive_list_node class intrusive_list_node
{ {
@ -85,7 +85,7 @@ namespace cppast
return *this; return *this;
} }
intrusive_list_iterator operator++(int)noexcept intrusive_list_iterator operator++(int) noexcept
{ {
auto tmp = *this; auto tmp = *this;
++(*this); ++(*this);
@ -120,15 +120,15 @@ namespace cppast
intrusive_list() = default; intrusive_list() = default;
//=== modifiers ===// //=== modifiers ===//
template <typename Dummy = T, typename = typename std::enable_if< template <typename Dummy = T,
std::is_same<Dummy, cpp_file>::value>::type> typename = typename std::enable_if<std::is_same<Dummy, cpp_file>::value>::type>
void push_back(std::unique_ptr<T> obj) noexcept void push_back(std::unique_ptr<T> obj) noexcept
{ {
push_back_impl(std::move(obj)); push_back_impl(std::move(obj));
} }
template <typename U, typename = typename std::enable_if< template <typename U,
!std::is_same<T, cpp_file>::value, U>::type> 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 void push_back(const U& parent, std::unique_ptr<T> obj) noexcept
{ {
push_back_impl(std::move(obj)); push_back_impl(std::move(obj));
@ -210,10 +210,8 @@ namespace cppast
class iteratable_intrusive_list class iteratable_intrusive_list
{ {
public: public:
iteratable_intrusive_list(type_safe::object_ref<const intrusive_list<T>> list) iteratable_intrusive_list(type_safe::object_ref<const intrusive_list<T>> list) : list_(list)
: list_(list) {}
{
}
bool empty() const noexcept bool empty() const noexcept
{ {
@ -235,7 +233,7 @@ namespace cppast
private: private:
type_safe::object_ref<const intrusive_list<T>> list_; type_safe::object_ref<const intrusive_list<T>> list_;
}; };
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_INTRUSIVE_LIST_HPP_INCLUDED #endif // CPPAST_INTRUSIVE_LIST_HPP_INCLUDED

View file

@ -12,10 +12,10 @@
namespace cppast namespace cppast
{ {
/// Describes a physical source location attached to a [cppast::diagnostic](). /// Describes a physical source location attached to a [cppast::diagnostic]().
/// \notes All information might be unavailable. /// \notes All information might be unavailable.
struct source_location struct source_location
{ {
type_safe::optional<std::string> entity; type_safe::optional<std::string> entity;
type_safe::optional<std::string> file; type_safe::optional<std::string> file;
type_safe::optional<unsigned> line, column; type_safe::optional<unsigned> line, column;
@ -80,22 +80,23 @@ namespace cppast
return result; return result;
} }
}; };
/// The severity of a [cppast::diagnostic](). /// The severity of a [cppast::diagnostic]().
enum class severity enum class severity
{ {
debug, //< A debug diagnostic that is just for debugging purposes. debug, //< A debug diagnostic that is just for debugging purposes.
info, //< An informational message. info, //< An informational message.
warning, //< A warning that doesn't impact AST generation. warning, //< A warning that doesn't impact AST generation.
error, //< A non-critical error that does impact AST generation but not critically. error, //< A non-critical error that does impact AST generation but not critically.
critical, //< A critical error where AST generation isn't possible. 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. /// \notes This will usually result in an exception being thrown after the diagnostic has been
}; /// displayed.
};
/// \returns A human-readable string describing the severity. /// \returns A human-readable string describing the severity.
inline const char* to_string(severity s) noexcept inline const char* to_string(severity s) noexcept
{ {
switch (s) switch (s)
{ {
case severity::debug: case severity::debug:
@ -111,20 +112,20 @@ namespace cppast
} }
return "programmer error"; return "programmer error";
} }
/// A diagnostic. /// A diagnostic.
/// ///
/// It represents an error message from a [cppast::parser](). /// It represents an error message from a [cppast::parser]().
struct diagnostic struct diagnostic
{ {
std::string message; std::string message;
source_location location; source_location location;
cppast::severity severity; cppast::severity severity;
}; };
namespace detail namespace detail
{ {
template <typename... Args> template <typename... Args>
std::string format(Args&&... args) std::string format(Args&&... args)
{ {
@ -133,16 +134,16 @@ namespace cppast
(void)dummy; (void)dummy;
return stream.str(); return stream.str();
} }
} // namespace detail } // namespace detail
/// Creates a diagnostic. /// Creates a diagnostic.
/// \returns A diagnostic with the specified severity and location. /// \returns A diagnostic with the specified severity and location.
/// The message is created by streaming each argument in order to a [std::ostringstream](). /// The message is created by streaming each argument in order to a [std::ostringstream]().
template <typename... Args> template <typename... Args>
diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args) diagnostic format_diagnostic(severity sev, source_location loc, Args&&... args)
{ {
return {detail::format(std::forward<Args>(args)...), std::move(loc), sev}; return {detail::format(std::forward<Args>(args)...), std::move(loc), sev};
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED #endif // CPPAST_DIAGNOSTIC_HPP_INCLUDED

View file

@ -11,12 +11,12 @@
namespace cppast namespace cppast
{ {
/// Base class for a [cppast::diagnostic]() logger. /// Base class for a [cppast::diagnostic]() logger.
/// ///
/// Its task is controlling how diagnostic are being displayed. /// Its task is controlling how diagnostic are being displayed.
class diagnostic_logger class diagnostic_logger
{ {
public: public:
/// \effects Creates it either as verbose or not. /// \effects Creates it either as verbose or not.
explicit diagnostic_logger(bool is_verbose = false) noexcept : verbose_(is_verbose) {} explicit diagnostic_logger(bool is_verbose = false) noexcept : verbose_(is_verbose) {}
@ -26,7 +26,8 @@ namespace cppast
/// \effects Logs the diagnostic by invoking the `do_log()` member function. /// \effects Logs the diagnostic by invoking the `do_log()` member function.
/// \returns Whether or not the diagnostic was logged. /// \returns Whether or not the diagnostic was logged.
/// \notes `source` points to a string literal that gives additional context to what generates the message. /// \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; bool log(const char* source, const diagnostic& d) const;
/// \effects Sets whether or not the logger prints debugging diagnostics. /// \effects Sets whether or not the logger prints debugging diagnostics.
@ -41,29 +42,29 @@ namespace cppast
return verbose_; return verbose_;
} }
private: private:
virtual bool do_log(const char* source, const diagnostic& d) const = 0; virtual bool do_log(const char* source, const diagnostic& d) const = 0;
bool verbose_; bool verbose_;
}; };
/// \returns The default logger object. /// \returns The default logger object.
type_safe::object_ref<const diagnostic_logger> default_logger() noexcept; type_safe::object_ref<const diagnostic_logger> default_logger() noexcept;
/// \returns The default verbose logger object. /// \returns The default verbose logger object.
type_safe::object_ref<const diagnostic_logger> default_verbose_logger() noexcept; type_safe::object_ref<const diagnostic_logger> default_verbose_logger() noexcept;
/// A [cppast::diagnostic_logger]() that logs to `stderr`. /// A [cppast::diagnostic_logger]() that logs to `stderr`.
/// ///
/// It prints all diagnostics in an implementation-defined format. /// It prints all diagnostics in an implementation-defined format.
class stderr_diagnostic_logger final : public diagnostic_logger class stderr_diagnostic_logger final : public diagnostic_logger
{ {
public: public:
using diagnostic_logger::diagnostic_logger; using diagnostic_logger::diagnostic_logger;
private: private:
bool do_log(const char* source, const diagnostic& d) const override; bool do_log(const char* source, const diagnostic& d) const override;
}; };
} // namespace cppast } // namespace cppast
#endif // CPPAST_DIAGNOSTIC_LOGGER_HPP_INCLUDED #endif // CPPAST_DIAGNOSTIC_LOGGER_HPP_INCLUDED

View file

@ -11,11 +11,11 @@
namespace cppast namespace cppast
{ {
class libclang_compile_config; class libclang_compile_config;
class libclang_compilation_database; 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);
@ -33,24 +33,24 @@ namespace cppast
void for_each_file(const libclang_compilation_database& database, void* user_data, void for_each_file(const libclang_compilation_database& database, void* user_data,
void (*callback)(void*, std::string)); void (*callback)(void*, std::string));
} // namespace detail } // namespace detail
/// The exception thrown when a fatal parse error occurs. /// The exception thrown when a fatal parse error occurs.
class libclang_error final : public std::runtime_error class libclang_error final : public std::runtime_error
{ {
public: public:
/// \effects Creates it with a message. /// \effects Creates it with a message.
libclang_error(std::string msg) : std::runtime_error(std::move(msg)) {} libclang_error(std::string msg) : std::runtime_error(std::move(msg)) {}
}; };
/// A compilation database. /// A compilation database.
/// ///
/// This represents a `compile_commands.json` file, /// This represents a `compile_commands.json` file,
/// which stores all the commands needed to compile a set of files. /// 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. /// It can be generated by CMake using the `CMAKE_EXPORT_COMPILE_COMMANDS` option.
class libclang_compilation_database class libclang_compilation_database
{ {
public: public:
/// \effects Creates it giving the directory where the `compile_commands.json` file is located. /// \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. /// \throws `libclang_error` if the database could not be loaded or found.
libclang_compilation_database(const std::string& build_directory); libclang_compilation_database(const std::string& build_directory);
@ -80,24 +80,25 @@ namespace cppast
return has_config(file_name.c_str()); return has_config(file_name.c_str());
} }
private: private:
using database = void*; using database = void*;
database database_; database database_;
friend libclang_compile_config; friend libclang_compile_config;
friend void detail::for_each_file(const libclang_compilation_database& database, friend void detail::for_each_file(const libclang_compilation_database& database,
void* user_data, void (*callback)(void*, std::string)); void* user_data, void (*callback)(void*, std::string));
}; };
/// Compilation config for the [cppast::libclang_parser](). /// Compilation config for the [cppast::libclang_parser]().
class libclang_compile_config final : public compile_config class libclang_compile_config final : public compile_config
{ {
public: public:
/// Creates the default configuration. /// Creates the default configuration.
/// ///
/// \effects It will set the clang binary determined by the build system, /// \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. /// 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__`. /// It will also define `__cppast__` with the value `"libclang"` as well as `__cppast_major__`
/// and `__cppast_minor__`.
libclang_compile_config(); libclang_compile_config();
/// Creates the configuration stored in the database. /// Creates the configuration stored in the database.
@ -110,15 +111,15 @@ namespace cppast
/// you need to pass in the file name of the corresponding source file, /// you need to pass in the file name of the corresponding source file,
/// if you want to parse one. /// if you want to parse one.
/// \notes It will only consider options you could also set by the other functions. /// \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. /// \notes The file key will include the specified directory in the JSON, if it is not a full
libclang_compile_config(const libclang_compilation_database& database, /// path.
const std::string& file); libclang_compile_config(const libclang_compilation_database& database, const std::string& file);
libclang_compile_config(const libclang_compile_config& other) = default; libclang_compile_config(const libclang_compile_config& other) = default;
libclang_compile_config& operator=(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. /// \effects Sets the path to the location of the `clang++` binary and the version of that
/// \notes It will be used for preprocessing. /// binary. \notes It will be used for preprocessing.
void set_clang_binary(std::string binary, int major, int minor, int patch) void set_clang_binary(std::string binary, int major, int minor, int patch)
{ {
clang_binary_ = std::move(binary); clang_binary_ = std::move(binary);
@ -134,13 +135,12 @@ namespace cppast
/// \effects Sets whether or not the fast preprocessor is enabled. /// \effects Sets whether or not the fast preprocessor is enabled.
/// Default value is `false`. /// Default value is `false`.
/// \notes The fast preprocessor gets a list of all macros that are defined in the translation unit, /// \notes The fast preprocessor gets a list of all macros that are defined in the translation
/// then preprocesses it without resolving includes but manually defining the list of macros to ensure correctness. /// unit, then preprocesses it without resolving includes but manually defining the list of
/// Later stages will use the includes again. /// macros to ensure correctness. Later stages will use the includes again. This hack breaks if
/// This hack breaks if you define the same macro multiple times in the file being parsed (headers don't matter) /// you define the same macro multiple times in the file being parsed (headers don't matter) or
/// or you rely on the order of macro directives. /// you rely on the order of macro directives. \notes If this option is `true`, the full file
/// \notes If this option is `true`, the full file name of include directives is not available, /// name of include directives is not available, just the name as written in the source code.
/// just the name as written in the source code.
void fast_preprocessing(bool b) noexcept void fast_preprocessing(bool b) noexcept
{ {
fast_preprocessing_ = b; fast_preprocessing_ = b;
@ -155,7 +155,7 @@ namespace cppast
remove_comments_in_macro_ = b; remove_comments_in_macro_ = b;
} }
private: private:
void do_set_flags(cpp_standard standard, compile_flags flags) override; void do_set_flags(cpp_standard standard, compile_flags flags) override;
void do_add_include_dir(std::string path) override; void do_add_include_dir(std::string path) override;
@ -176,21 +176,22 @@ namespace cppast
bool remove_comments_in_macro_ : 1; bool remove_comments_in_macro_ : 1;
friend detail::libclang_compile_config_access; friend detail::libclang_compile_config_access;
}; };
/// Finds a configuration for a given file. /// Finds a configuration for a given file.
/// ///
/// \returns If the database contains a configuration for the given file, returns that configuration. /// \returns If the database contains a configuration for the given file, returns that
/// Otherwise removes the file extension of the file and tries the same procedure /// configuration. Otherwise removes the file extension of the file and tries the same procedure for
/// for common C++ header and source file extensions. /// common C++ header and source file extensions. \notes This function is intended to be used as the
/// \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/). /// basis for a `get_config` function of
type_safe::optional<libclang_compile_config> find_config_for( /// [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); const libclang_compilation_database& database, std::string file_name);
/// A parser that uses libclang. /// A parser that uses libclang.
class libclang_parser final : public parser class libclang_parser final : public parser
{ {
public: public:
using config = libclang_compile_config; using config = libclang_compile_config;
/// \effects Creates a parser using the default logger. /// \effects Creates a parser using the default logger.
@ -201,27 +202,28 @@ namespace cppast
~libclang_parser() noexcept override; ~libclang_parser() noexcept override;
private: private:
std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path, std::unique_ptr<cpp_file> do_parse(const cpp_entity_index& idx, std::string path,
const compile_config& config) const override; const compile_config& config) const override;
struct impl; struct impl;
std::unique_ptr<impl> pimpl_; std::unique_ptr<impl> pimpl_;
}; };
/// Parses multiple files using a [cppast::libclang_parser]() and a compilation database. /// 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, /// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser
/// and a `get_config` function using [cppast::find_config_for](). /// 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. /// \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](). /// \requires `FileParser` must use the libclang parser.
template <class FileParser, class Range> /// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
void parse_files(FileParser& parser, Range&& file_names, template <class FileParser, class Range>
void parse_files(FileParser& parser, Range&& file_names,
const libclang_compilation_database& database) const libclang_compilation_database& database)
{ {
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value, static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
"must use the libclang parser"); "must use the libclang parser");
parse_files(parser, std::forward<Range>(file_names), [&](const std::string& file) { parse_files(parser, std::forward<Range>(file_names), [&](const std::string& file) {
@ -230,19 +232,19 @@ namespace cppast
throw libclang_error("unable to find configuration for file '" + file + "'"); throw libclang_error("unable to find configuration for file '" + file + "'");
return config.value(); return config.value();
}); });
} }
/// Parses the files specified in a compilation database using a [cppast::libclang_parser](). /// Parses the files specified in a compilation database using a [cppast::libclang_parser]().
/// ///
/// \effects For each file specified in a compilation database, /// \effects For each file specified in a compilation database,
/// uses the `FileParser` to parse the file with the configuration specified in the 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/). /// \requires `FileParser` must have the same requirements as for
/// It must also use the libclang parser, /// [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](). /// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
template <class FileParser> template <class FileParser>
void parse_database(FileParser& parser, const libclang_compilation_database& database) void parse_database(FileParser& parser, const libclang_compilation_database& database)
{ {
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value, static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
"must use the libclang parser"); "must use the libclang parser");
struct data_t struct data_t
@ -256,7 +258,7 @@ namespace cppast
libclang_compile_config config(data.database, file); libclang_compile_config config(data.database, file);
data.parser.parse(std::move(file), std::move(config)); data.parser.parse(std::move(file), std::move(config));
}); });
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_LIBCLANG_PARSER_HPP_INCLUDED #endif // CPPAST_LIBCLANG_PARSER_HPP_INCLUDED

View file

@ -10,22 +10,23 @@
#include <cppast/compile_config.hpp> #include <cppast/compile_config.hpp>
#include <cppast/cpp_file.hpp> #include <cppast/cpp_file.hpp>
#include <cppast/cpp_preprocessor.hpp> #include <cppast/cpp_preprocessor.hpp>
#include <cppast/diagnostic_logger.hpp>
#include <cppast/diagnostic.hpp> #include <cppast/diagnostic.hpp>
#include <cppast/diagnostic_logger.hpp>
namespace cppast namespace cppast
{ {
class cpp_entity_index; class cpp_entity_index;
/// Base class for a parser. /// Base class for a parser.
/// ///
/// It reads a C++ source file and creates the matching [cppast::cpp_file](). /// It reads a C++ source file and creates the matching [cppast::cpp_file]().
/// Derived classes can implement how the file is parsed. /// 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](). /// \requires A derived class must provide an alias `config` which is the corresponding derived
class parser /// class of the [cppast::compile_config]().
{ class parser
public: {
public:
parser(const parser&) = delete; parser(const parser&) = delete;
parser& operator=(const parser&) = delete; parser& operator=(const parser&) = delete;
@ -33,9 +34,9 @@ namespace cppast
/// \effects Parses the given file. /// \effects Parses the given file.
/// \returns The [cppast::cpp_file]() object describing it. /// \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. /// It can be `nullptr`, if there was an error or the specified file already registered in the
/// \requires The dynamic type of `config` must match the required config type. /// index. \requires The dynamic type of `config` must match the required config type. \notes
/// \notes This function is thread safe. /// This function is thread safe.
std::unique_ptr<cpp_file> parse(const cpp_entity_index& idx, std::string path, std::unique_ptr<cpp_file> parse(const cpp_entity_index& idx, std::string path,
const compile_config& config) const const compile_config& config) const
{ {
@ -61,21 +62,21 @@ namespace cppast
return *logger_; return *logger_;
} }
protected: protected:
/// \effects Creates it giving it a reference to the logger it uses. /// \effects Creates it giving it a reference to the logger it uses.
explicit parser(type_safe::object_ref<const diagnostic_logger> logger) explicit parser(type_safe::object_ref<const diagnostic_logger> logger)
: logger_(logger), error_(false) : logger_(logger), error_(false)
{ {}
}
/// \effects Sets the error state. /// \effects Sets the error state.
/// This must be called when an error or critical diagnostic is logged and the AST is incomplete. /// This must be called when an error or critical diagnostic is logged and the AST is
/// incomplete.
void set_error() const noexcept void set_error() const noexcept
{ {
error_ = true; error_ = true;
} }
private: private:
/// \effects Parses the given file. /// \effects Parses the given file.
/// \returns The [cppast::cpp_file]() object describing it. /// \returns The [cppast::cpp_file]() object describing it.
/// \requires The function must be thread safe. /// \requires The function must be thread safe.
@ -84,37 +85,34 @@ namespace cppast
type_safe::object_ref<const diagnostic_logger> logger_; type_safe::object_ref<const diagnostic_logger> logger_;
mutable std::atomic<bool> error_; mutable std::atomic<bool> error_;
}; };
/// A simple `FileParser` that parses all files synchronously. /// A simple `FileParser` that parses all files synchronously.
/// ///
/// More advanced parsers could use a thread pool, for example. /// More advanced parsers could use a thread pool, for example.
template <class Parser> template <class Parser>
class simple_file_parser class simple_file_parser
{ {
static_assert(std::is_base_of<cppast::parser, Parser>::value, static_assert(std::is_base_of<cppast::parser, Parser>::value,
"Parser must be derived from cppast::parser"); "Parser must be derived from cppast::parser");
public: public:
using parser = Parser; using parser = Parser;
using config = typename Parser::config; using config = typename Parser::config;
/// \effects Creates a file parser populating the given index /// \effects Creates a file parser populating the given index
/// and using the parser created by forwarding the given arguments. /// and using the parser created by forwarding the given arguments.
template <typename... Args> template <typename... Args>
explicit simple_file_parser(type_safe::object_ref<const cpp_entity_index> idx, explicit simple_file_parser(type_safe::object_ref<const cpp_entity_index> idx, Args&&... args)
Args&&... args)
: parser_(std::forward<Args>(args)...), idx_(idx) : parser_(std::forward<Args>(args)...), idx_(idx)
{ {}
}
/// \effects Parses the given file using the given configuration. /// \effects Parses the given file using the given configuration.
/// \returns The parsed file or an empty optional, if a fatal error occurred. /// \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) type_safe::optional_ref<const cpp_file> parse(std::string path, const config& c)
{ {
parser_.logger().log("simple file parser", parser_.logger().log("simple file parser", diagnostic{"parsing file '" + path + "'",
diagnostic{"parsing file '" + path + "'", source_location(), source_location(), severity::info});
severity::info});
auto file = parser_.parse(*idx_, std::move(path), c); auto file = parser_.parse(*idx_, std::move(path), c);
auto ptr = file.get(); auto ptr = file.get();
if (file) if (file)
@ -147,83 +145,76 @@ namespace cppast
return type_safe::ref(files_); return type_safe::ref(files_);
} }
private: private:
Parser parser_; Parser parser_;
detail::intrusive_list<cpp_file> files_; detail::intrusive_list<cpp_file> files_;
type_safe::object_ref<const cpp_entity_index> idx_; type_safe::object_ref<const cpp_entity_index> idx_;
}; };
namespace detail namespace detail
{ {
struct std_begin struct std_begin
{ {};
};
struct adl_begin : std_begin struct adl_begin : std_begin
{ {};
};
struct member_begin : adl_begin struct member_begin : adl_begin
{ {};
};
template <class Range> template <class Range>
auto get_value_type_impl(member_begin, Range&& r) auto get_value_type_impl(member_begin, Range&& r) -> decltype(std::forward<Range>(r).begin());
-> decltype(std::forward<Range>(r).begin());
template <class Range> template <class Range>
auto get_value_type_impl(adl_begin, Range&& r) -> decltype(begin(std::forward<Range>(r))); auto get_value_type_impl(adl_begin, Range&& r) -> decltype(begin(std::forward<Range>(r)));
template <class Range> template <class Range>
auto get_value_type_impl(std_begin, Range&& r) auto get_value_type_impl(std_begin, Range&& r) -> decltype(std::begin(std::forward<Range>(r)));
-> decltype(std::begin(std::forward<Range>(r)));
template <class Range> template <class Range>
using value_type = decltype(*get_value_type_impl(member_begin{}, std::declval<Range>())); using value_type = decltype(*get_value_type_impl(member_begin{}, std::declval<Range>()));
} // namespace detail } // namespace detail
/// Parses multiple files using a given `FileParser`. /// Parses multiple files using a given `FileParser`.
/// ///
/// \effects Will call the `parse()` function for each path specified in the `file_names`, /// \effects Will call the `parse()` function for each path specified in the `file_names`,
/// using `get_confg` to determine the configuration. /// using `get_confg` to determine the configuration.
/// ///
/// \requires `FileParser` must be a class with the following members: /// \requires `FileParser` must be a class with the following members:
/// * `parser` - A typedef for the parser being used to do the parsing. /// * `parser` - A typedef for the parser being used to do the parsing.
/// * `config` - The same as `parser::config`. /// * `config` - The same as `parser::config`.
/// * `parse(path, config)` - Parses the given file with the configuration using its parser. /// * `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. /// The parsing can be executed in a separated thread, but then a copy of the configuration and path
/// \requires `Range` must be some type that can be iterated in a range-based for loop. /// must be created. \requires `Range` must be some type that can be iterated in a range-based for
/// \requires `Configuration` must be a function that returns a configuration of type `FileParser::config` when given a path. /// loop. \requires `Configuration` must be a function that returns a configuration of type
/// \unique_name parse_files_basic /// `FileParser::config` when given a path. \unique_name parse_files_basic \synopsis_return void
/// \synopsis_return void template <class FileParser, class Range, class Configuration>
template <class FileParser, class Range, class Configuration> auto parse_files(FileParser& parser, Range&& file_names, const Configuration& get_config) ->
auto parse_files(FileParser& parser, Range&& file_names, const Configuration& get_config) -> typename std::enable_if<std::is_same<
typename std::enable_if<std::is_same<typename std::decay<decltype(get_config( typename std::decay<decltype(get_config(std::declval<detail::value_type<Range>>()))>::type,
std::declval<detail::value_type<Range>>()))>::type,
typename FileParser::config>::value>::type typename FileParser::config>::value>::type
{ {
for (auto&& file : std::forward<Range>(file_names)) for (auto&& file : std::forward<Range>(file_names))
{ {
auto&& config = get_config(file); auto&& config = get_config(file);
parser.parse(std::forward<decltype(file)>(file), parser.parse(std::forward<decltype(file)>(file), std::forward<decltype(config)>(config));
std::forward<decltype(config)>(config));
}
} }
}
/// Parses multiple files using a given `FileParser` and configuration. /// 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, /// \effects Invokes [cppast::parse_files](standardese://parse_files_basic/) passing it the parser
/// and a function that returns the same configuration for each file. /// and file names, and a function that returns the same configuration for each file.
template <class FileParser, class Range> template <class FileParser, class Range>
void parse_files(FileParser& parser, Range&& file_names, typename FileParser::config config) void parse_files(FileParser& parser, Range&& file_names, typename FileParser::config config)
{ {
parse_files(parser, std::forward<Range>(file_names), parse_files(parser, std::forward<Range>(file_names),
[&](const std::string&) { return config; }); [&](const std::string&) { return config; });
} }
/// Parses all files included by `file`. /// Parses all files included by `file`.
/// \effects For each [cppast::cpp_include_directive]() in file it will parse the included file. /// \effects For each [cppast::cpp_include_directive]() in file it will parse the included file.
template <class FileParser> template <class FileParser>
std::size_t resolve_includes(FileParser& parser, const cpp_file& file, std::size_t resolve_includes(FileParser& parser, const cpp_file& file,
typename FileParser::config config) typename FileParser::config config)
{ {
auto count = 0u; auto count = 0u;
for (auto& entity : file) for (auto& entity : file)
{ {
@ -235,7 +226,7 @@ namespace cppast
} }
} }
return count; return count;
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_PARSER_HPP_INCLUDED #endif // CPPAST_PARSER_HPP_INCLUDED

View file

@ -13,9 +13,9 @@
namespace cppast namespace cppast
{ {
/// Information about the state of a visit operation. /// Information about the state of a visit operation.
struct visitor_info struct visitor_info
{ {
enum event_type enum event_type
{ {
leaf_entity, //< Callback called for a leaf entity without children. leaf_entity, //< Callback called for a leaf entity without children.
@ -45,11 +45,11 @@ namespace cppast
{ {
return !is_new_entity(); return !is_new_entity();
} }
}; };
/// A more expressive way to specify the return of a visit operation. /// A more expressive way to specify the return of a visit operation.
enum visitor_result : bool enum visitor_result : bool
{ {
/// Visit should continue. /// Visit should continue.
/// \group continue /// \group continue
continue_visit = true, continue_visit = true,
@ -62,26 +62,25 @@ namespace cppast
continue_visit_no_children = false, continue_visit_no_children = false,
/// Visit should be aborted. /// Visit should be aborted.
/// \notes This only happens when the event is not [cppast::visitor_info::container_entity_enter](). /// \notes This only happens when the event is not
/// [cppast::visitor_info::container_entity_enter]().
abort_visit = false, abort_visit = false,
}; };
/// \exclude /// \exclude
namespace detail namespace detail
{ {
using visitor_callback_t = bool (*)(void* mem, const cpp_entity&, visitor_info info); using visitor_callback_t = bool (*)(void* mem, const cpp_entity&, visitor_info info);
struct visitor_info_void struct visitor_info_void
{ {};
};
struct visitor_info_bool : visitor_info_void struct visitor_info_bool : visitor_info_void
{ {};
};
template <typename Func> template <typename Func>
visitor_callback_t get_visitor_callback( visitor_callback_t get_visitor_callback(
visitor_info_bool, decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info_bool,
visitor_info{})) = true) decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{})) = true)
{ {
return [](void* mem, const cpp_entity& e, visitor_info info) { return [](void* mem, const cpp_entity& e, visitor_info info) {
auto& func = *static_cast<Func*>(mem); auto& func = *static_cast<Func*>(mem);
@ -92,8 +91,7 @@ namespace cppast
template <typename Func> template <typename Func>
visitor_callback_t get_visitor_callback( visitor_callback_t get_visitor_callback(
visitor_info_void, visitor_info_void,
decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{}), decltype(std::declval<Func>()(std::declval<const cpp_entity&>(), visitor_info{}), 0) = 0)
0) = 0)
{ {
return [](void* mem, const cpp_entity& e, visitor_info info) { return [](void* mem, const cpp_entity& e, visitor_info info) {
auto& func = *static_cast<Func*>(mem); auto& func = *static_cast<Func*>(mem);
@ -110,38 +108,38 @@ namespace cppast
bool visit(const cpp_entity& e, visitor_callback_t cb, void* functor, bool visit(const cpp_entity& e, visitor_callback_t cb, void* functor,
cpp_access_specifier_kind cur_access, bool last_child); cpp_access_specifier_kind cur_access, bool last_child);
} // namespace detail } // namespace detail
/// Visits a [cppast::cpp_entity]() and children. /// Visits a [cppast::cpp_entity]() and children.
/// ///
/// \effects It will invoke the callback - the visitor - for the current entity and children, /// \effects It will invoke the callback - the visitor - for the current entity and children,
/// as controlled by the [cppast::visitor_result](). /// as controlled by the [cppast::visitor_result]().
/// The visitor is given a reference to the currently visited entity and the [cppast::visitor_info](). /// 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. /// \requires The visitor must be callable as specified and must either return `bool` or nothing.
template <typename Func> /// If it returns nothing, a return value [cppast::visitor_result::continue_visit]() is assumed.
void visit(const cpp_entity& e, Func f) template <typename Func>
{ void visit(const cpp_entity& e, Func f)
{
detail::visit(e, detail::get_visitor_callback<Func>(), &f, cpp_public, false); detail::visit(e, detail::get_visitor_callback<Func>(), &f, cpp_public, false);
} }
/// The result of a visitor filter operation. /// The result of a visitor filter operation.
enum class visit_filter enum class visit_filter
{ {
include = true, //< The entity is included. include = true, //< The entity is included.
exclude = false, //< The entity is excluded and will not be visited. exclude = false, //< The entity is excluded and will not be visited.
exclude_and_children = exclude_and_children
2, //< The entity and all direct children are excluded and will not be visited. = 2, //< The entity and all direct children are excluded and will not be visited.
}; };
namespace detail namespace detail
{ {
using visitor_filter_t = visit_filter (*)(const cpp_entity&); using visitor_filter_t = visit_filter (*)(const cpp_entity&);
template <typename Filter> template <typename Filter>
auto invoke_visit_filter(int, Filter f, const cpp_entity& e, auto invoke_visit_filter(int, Filter f, const cpp_entity& e, cpp_access_specifier_kind access)
cpp_access_specifier_kind access)
-> decltype(static_cast<visit_filter>(f(e, access))) -> decltype(static_cast<visit_filter>(f(e, access)))
{ {
return static_cast<visit_filter>(f(e, access)); return static_cast<visit_filter>(f(e, access));
@ -153,20 +151,22 @@ namespace cppast
{ {
return static_cast<visit_filter>(f(e)); return static_cast<visit_filter>(f(e));
} }
} // namespace detail } // namespace detail
/// Visits a [cppast::cpp_entity]() and children that pass a given filter. /// 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. /// \effects It behaves like the non-filtered visit except it will only invoke the visitor for
/// 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](). /// entities that match the filter. The filter is a predicate that will be invoked with the current
/// Visit will behave accordingly. /// 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. /// \requires The visitor must be as specified for the other overload.
/// It must return a `bool` or a [cppast::visit_filter](). /// The filter must be a function taking a [cppast::cpp_entity]() as first parameter and optionally
template <typename Func, typename Filter> /// a [cppast::cpp_access_specifier_kind]() as second. It must return a `bool` or a
void visit(const cpp_entity& e, Filter filter, Func f) /// [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 { visit(e, [&](const cpp_entity& e, const visitor_info& info) -> bool {
auto result = detail::invoke_visit_filter(0, filter, e, info.access); auto result = detail::invoke_visit_filter(0, filter, e, info.access);
switch (result) switch (result)
@ -184,11 +184,11 @@ namespace cppast
} }
return continue_visit; return continue_visit;
}); });
} }
/// \exclude /// \exclude
namespace detail namespace detail
{ {
template <cpp_entity_kind... K> template <cpp_entity_kind... K>
bool has_one_of_kind(const cpp_entity& e) bool has_one_of_kind(const cpp_entity& e)
{ {
@ -201,43 +201,42 @@ namespace cppast
return result; return result;
} }
} // namespace detail } // namespace detail
/// Generates a blacklist visitor filter. /// Generates a blacklist visitor filter.
/// ///
/// \returns A visitor filter that excludes all entities having one of the specified kinds. /// \returns A visitor filter that excludes all entities having one of the specified kinds.
template <cpp_entity_kind... Kinds> template <cpp_entity_kind... Kinds>
detail::visitor_filter_t blacklist() detail::visitor_filter_t blacklist()
{ {
return [](const cpp_entity& e) { return [](const cpp_entity& e) {
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude : return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude : visit_filter::include;
visit_filter::include;
}; };
} }
/// Generates a blacklist visitor filter. /// Generates a blacklist visitor filter.
/// ///
/// \returns A visitor filter that excludes all entities having one of the specified kinds and children of those entities. /// \returns A visitor filter that excludes all entities having one of the specified kinds and
template <cpp_entity_kind... Kinds> /// children of those entities.
detail::visitor_filter_t blacklist_and_children() template <cpp_entity_kind... Kinds>
{ detail::visitor_filter_t blacklist_and_children()
{
return [](const cpp_entity& e) { return [](const cpp_entity& e) {
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude_and_children : return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::exclude_and_children
visit_filter::include; : visit_filter::include;
}; };
} }
/// Generates a whitelist visitor filter. /// Generates a whitelist visitor filter.
/// ///
/// \returns A visitor filter that excludes all entities having not one of the specified kinds. /// \returns A visitor filter that excludes all entities having not one of the specified kinds.
template <cpp_entity_kind... Kinds> template <cpp_entity_kind... Kinds>
detail::visitor_filter_t whitelist() detail::visitor_filter_t whitelist()
{ {
return [](const cpp_entity& e) { return [](const cpp_entity& e) {
return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::include : return detail::has_one_of_kind<Kinds...>(e) ? visit_filter::include : visit_filter::exclude;
visit_filter::exclude;
}; };
} }
} // namespace cppast } // namespace cppast
#endif // CPPAST_VISITOR_HPP_INCLUDED #endif // CPPAST_VISITOR_HPP_INCLUDED

View file

@ -29,41 +29,41 @@ using namespace cppast;
namespace namespace
{ {
void opening_brace(const code_generator::output& output) void opening_brace(const code_generator::output& output)
{ {
if (output.formatting().is_set(formatting_flags::brace_nl)) if (output.formatting().is_set(formatting_flags::brace_nl))
output << newl; output << newl;
else if (output.formatting().is_set(formatting_flags::brace_ws)) else if (output.formatting().is_set(formatting_flags::brace_ws))
output << whitespace; output << whitespace;
output << punctuation("{"); output << punctuation("{");
} }
void comma(const code_generator::output& output) void comma(const code_generator::output& output)
{ {
output << punctuation(","); output << punctuation(",");
if (output.formatting().is_set(formatting_flags::comma_ws)) if (output.formatting().is_set(formatting_flags::comma_ws))
output << whitespace; output << whitespace;
} }
void bracket_ws(const code_generator::output& output) void bracket_ws(const code_generator::output& output)
{ {
if (output.formatting().is_set(formatting_flags::bracket_ws)) if (output.formatting().is_set(formatting_flags::bracket_ws))
output << whitespace; output << whitespace;
} }
void operator_ws(const code_generator::output& output) void operator_ws(const code_generator::output& output)
{ {
if (output.formatting().is_set(formatting_flags::operator_ws)) if (output.formatting().is_set(formatting_flags::operator_ws))
output << whitespace; output << whitespace;
} }
bool generate_code_impl(code_generator& generator, const cpp_entity& e, bool generate_code_impl(code_generator& generator, const cpp_entity& e,
cpp_access_specifier_kind cur_access); cpp_access_specifier_kind cur_access);
template <class Container, typename Sep> template <class Container, typename Sep>
bool write_container(code_generator::output& output, const Container& cont, Sep s, bool write_container(code_generator::output& output, const Container& cont, Sep s,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
auto need_sep = false; auto need_sep = false;
for (auto& child : cont) for (auto& child : cont)
{ {
@ -76,11 +76,11 @@ namespace
} }
} }
return need_sep; return need_sep;
} }
bool generate_file(code_generator& generator, const cpp_file& f, bool generate_file(code_generator& generator, const cpp_file& f,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(f), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(f), cur_access);
if (output) if (output)
{ {
@ -92,20 +92,20 @@ namespace
output.container_end(); output.container_end();
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_macro_parameter(code_generator& generator, const cpp_macro_parameter& param, bool generate_macro_parameter(code_generator& generator, const cpp_macro_parameter& param,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access);
if (output) if (output)
output << identifier(param.name()); output << identifier(param.name());
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_macro_definition(code_generator& generator, const cpp_macro_definition& def, bool generate_macro_definition(code_generator& generator, const cpp_macro_definition& def,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(def), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(def), cur_access);
if (output) if (output)
{ {
@ -128,13 +128,12 @@ namespace
output << newl; output << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_include_directive(code_generator& generator, const cpp_include_directive& include, bool generate_include_directive(code_generator& generator, const cpp_include_directive& include,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(include), code_generator::output output(type_safe::ref(generator), type_safe::ref(include), cur_access);
cur_access);
if (output) if (output)
{ {
output << preprocessor_token("#include") << whitespace; output << preprocessor_token("#include") << whitespace;
@ -150,13 +149,12 @@ namespace
output << newl; output << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_language_linkage(code_generator& generator, const cpp_language_linkage& linkage, bool generate_language_linkage(code_generator& generator, const cpp_language_linkage& linkage,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(linkage), code_generator::output output(type_safe::ref(generator), type_safe::ref(linkage), cur_access);
cur_access);
if (output) if (output)
{ {
output << keyword("extern") << whitespace << string_literal(linkage.name()); output << keyword("extern") << whitespace << string_literal(linkage.name());
@ -177,11 +175,11 @@ namespace
} }
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_namespace(code_generator& generator, const cpp_namespace& ns, bool generate_namespace(code_generator& generator, const cpp_namespace& ns,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(ns), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(ns), cur_access);
if (output) if (output)
{ {
@ -198,11 +196,11 @@ namespace
output << punctuation("}") << newl; output << punctuation("}") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_namespace_alias(code_generator& generator, const cpp_namespace_alias& alias, bool generate_namespace_alias(code_generator& generator, const cpp_namespace_alias& alias,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access);
if (output) if (output)
{ {
@ -215,34 +213,32 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_using_directive(code_generator& generator, const cpp_using_directive& directive, bool generate_using_directive(code_generator& generator, const cpp_using_directive& directive,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(directive), code_generator::output output(type_safe::ref(generator), type_safe::ref(directive), cur_access);
cur_access);
if (output) if (output)
output << keyword("using") << whitespace << keyword("namespace") << whitespace output << keyword("using") << whitespace << keyword("namespace") << whitespace
<< directive.target() << punctuation(";") << newl; << directive.target() << punctuation(";") << newl;
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_using_declaration(code_generator& generator, bool generate_using_declaration(code_generator& generator, const cpp_using_declaration& declaration,
const cpp_using_declaration& declaration,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(declaration), code_generator::output output(type_safe::ref(generator), type_safe::ref(declaration),
cur_access); cur_access);
if (output) if (output)
output << keyword("using") << whitespace << declaration.target() << punctuation(";") output << keyword("using") << whitespace << declaration.target() << punctuation(";")
<< newl; << newl;
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_type_alias(code_generator& generator, const cpp_type_alias& alias, bool generate_type_alias(code_generator& generator, const cpp_type_alias& alias,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access);
if (output) if (output)
{ {
@ -255,11 +251,11 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_enum_value(code_generator& generator, const cpp_enum_value& value, bool generate_enum_value(code_generator& generator, const cpp_enum_value& value,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(value), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(value), cur_access);
if (output) if (output)
{ {
@ -267,18 +263,17 @@ namespace
if (value.value()) if (value.value())
{ {
output << operator_ws << punctuation("=") << operator_ws; output << operator_ws << punctuation("=") << operator_ws;
detail:: detail::write_expression(output,
write_expression(output,
value.value() value.value()
.value()); // should have named something differently... .value()); // should have named something differently...
} }
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_enum(code_generator& generator, const cpp_enum& e, bool generate_enum(code_generator& generator, const cpp_enum& e,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(e), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(e), cur_access);
if (output) if (output)
{ {
@ -314,28 +309,28 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_access_specifier(code_generator::output& output, cpp_access_specifier_kind access) void write_access_specifier(code_generator::output& output, cpp_access_specifier_kind access)
{ {
output.unindent(); output.unindent();
output << keyword(to_string(access)) << punctuation(":"); output << keyword(to_string(access)) << punctuation(":");
output.indent(); output.indent();
} }
bool generate_access_specifier(code_generator& generator, const cpp_access_specifier& access, bool generate_access_specifier(code_generator& generator, const cpp_access_specifier& access,
cpp_access_specifier_kind) cpp_access_specifier_kind)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(access), code_generator::output output(type_safe::ref(generator), type_safe::ref(access),
access.access_specifier()); access.access_specifier());
if (output) if (output)
write_access_specifier(output, access.access_specifier()); write_access_specifier(output, access.access_specifier());
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_base_class(code_generator& generator, const cpp_base_class& base, bool generate_base_class(code_generator& generator, const cpp_base_class& base,
cpp_access_specifier_kind) cpp_access_specifier_kind)
{ {
DEBUG_ASSERT(base.parent() && base.parent().value().kind() == cpp_entity_kind::class_t, DEBUG_ASSERT(base.parent() && base.parent().value().kind() == cpp_entity_kind::class_t,
detail::assert_handler{}); detail::assert_handler{});
auto parent_kind = static_cast<const cpp_class&>(base.parent().value()).class_kind(); auto parent_kind = static_cast<const cpp_class&>(base.parent().value()).class_kind();
@ -358,11 +353,11 @@ namespace
output << identifier(base.name()); output << identifier(base.name());
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_specialization_arguments(code_generator::output& output, void write_specialization_arguments(code_generator::output& output,
const cpp_template_specialization& spec) const cpp_template_specialization& spec)
{ {
if (spec.arguments_exposed()) if (spec.arguments_exposed())
detail::write_template_arguments(output, spec.arguments()); detail::write_template_arguments(output, spec.arguments());
else if (!spec.unexposed_arguments().empty()) else if (!spec.unexposed_arguments().empty())
@ -371,10 +366,10 @@ namespace
detail::write_token_string(output, spec.unexposed_arguments()); detail::write_token_string(output, spec.unexposed_arguments());
output << bracket_ws << punctuation(">"); output << bracket_ws << punctuation(">");
} }
} }
void write_bases(code_generator& generator, code_generator::output& output, const cpp_class& c) void write_bases(code_generator& generator, code_generator::output& output, const cpp_class& c)
{ {
auto need_sep = false; auto need_sep = false;
auto first = true; auto first = true;
for (auto& base : c.bases()) for (auto& base : c.bases())
@ -389,12 +384,12 @@ namespace
output << comma; output << comma;
need_sep = generate_base_class(generator, base, cpp_public); need_sep = generate_base_class(generator, base, cpp_public);
} }
} }
bool generate_class(code_generator& generator, const cpp_class& c, bool generate_class(code_generator& generator, const cpp_class& c,
cpp_access_specifier_kind cur_access, cpp_access_specifier_kind cur_access,
type_safe::optional_ref<const cpp_template_specialization> spec = nullptr) type_safe::optional_ref<const cpp_template_specialization> spec = nullptr)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(c), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(c), cur_access);
if (output) if (output)
{ {
@ -423,8 +418,7 @@ namespace
output.indent(); output.indent();
auto need_sep = false; auto need_sep = false;
auto last_access = auto last_access = c.class_kind() == cpp_class_kind::class_t ? cpp_private : cpp_public;
c.class_kind() == cpp_class_kind::class_t ? cpp_private : cpp_public;
auto last_written_access = last_access; auto last_written_access = last_access;
for (auto& member : c) for (auto& member : c)
{ {
@ -455,11 +449,11 @@ namespace
} }
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool write_variable_base(code_generator::output& output, const cpp_variable_base& var, bool write_variable_base(code_generator::output& output, const cpp_variable_base& var,
const std::string& name) const std::string& name)
{ {
detail::write_type(output, var.type(), name); detail::write_type(output, var.type(), name);
if (var.default_value()) if (var.default_value())
@ -468,11 +462,11 @@ namespace
detail::write_expression(output, var.default_value().value()); detail::write_expression(output, var.default_value().value());
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_storage_class(code_generator::output& output, cpp_storage_class_specifiers storage, void write_storage_class(code_generator::output& output, cpp_storage_class_specifiers storage,
bool is_constexpr) bool is_constexpr)
{ {
if (is_static(storage)) if (is_static(storage))
output << keyword("static") << whitespace; output << keyword("static") << whitespace;
if (is_extern(storage)) if (is_extern(storage))
@ -481,11 +475,11 @@ namespace
output << keyword("thread_local") << whitespace; output << keyword("thread_local") << whitespace;
if (is_constexpr) if (is_constexpr)
output << keyword("constexpr") << whitespace; output << keyword("constexpr") << whitespace;
} }
bool generate_variable(code_generator& generator, const cpp_variable& var, bool generate_variable(code_generator& generator, const cpp_variable& var,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access);
if (output) if (output)
{ {
@ -495,11 +489,11 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_member_variable(code_generator& generator, const cpp_member_variable& var, bool generate_member_variable(code_generator& generator, const cpp_member_variable& var,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access);
if (output) if (output)
{ {
@ -509,11 +503,11 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_bitfield(code_generator& generator, const cpp_bitfield& var, bool generate_bitfield(code_generator& generator, const cpp_bitfield& var,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access);
if (output) if (output)
{ {
@ -525,19 +519,19 @@ namespace
output << punctuation(";") << newl; output << punctuation(";") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_function_parameter(code_generator& generator, const cpp_function_parameter& param, bool generate_function_parameter(code_generator& generator, const cpp_function_parameter& param,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access);
if (output) if (output)
write_variable_base(output, param, param.name()); write_variable_base(output, param, param.name());
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_function_parameters(code_generator::output& output, const cpp_function_base& base) void write_function_parameters(code_generator::output& output, const cpp_function_base& base)
{ {
output << punctuation("(") << bracket_ws; output << punctuation("(") << bracket_ws;
auto need_sep = write_container(output, base.parameters(), comma, cpp_public); auto need_sep = write_container(output, base.parameters(), comma, cpp_public);
if (base.is_variadic()) if (base.is_variadic())
@ -547,10 +541,10 @@ namespace
output << punctuation("..."); output << punctuation("...");
} }
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
} }
void write_noexcept(code_generator::output& output, const cpp_function_base& base, bool need_ws) void write_noexcept(code_generator::output& output, const cpp_function_base& base, bool need_ws)
{ {
if (!base.noexcept_condition()) if (!base.noexcept_condition())
return; return;
else if (need_ws) else if (need_ws)
@ -574,11 +568,11 @@ namespace
detail::write_expression(output, cond); detail::write_expression(output, cond);
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
} }
} }
void write_function_body(code_generator::output& output, const cpp_function_base& base, void write_function_body(code_generator::output& output, const cpp_function_base& base,
bool is_pure_virtual) bool is_pure_virtual)
{ {
switch (base.body_kind()) switch (base.body_kind())
{ {
case cpp_function_declaration: case cpp_function_declaration:
@ -597,12 +591,12 @@ namespace
<< punctuation(";") << newl; << punctuation(";") << newl;
break; break;
} }
} }
bool generate_function( bool generate_function(code_generator& generator, const cpp_function& func,
code_generator& generator, const cpp_function& func, cpp_access_specifier_kind cur_access, cpp_access_specifier_kind cur_access,
type_safe::optional_ref<const cpp_template_specialization> spec = nullptr) type_safe::optional_ref<const cpp_template_specialization> spec = nullptr)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access);
if (output) if (output)
{ {
@ -640,17 +634,17 @@ namespace
write_function_body(output, func, false); write_function_body(output, func, false);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_prefix_virtual(code_generator::output& output, const cpp_virtual& virt) void write_prefix_virtual(code_generator::output& output, const cpp_virtual& virt)
{ {
if (is_virtual(virt)) if (is_virtual(virt))
output << keyword("virtual") << whitespace; output << keyword("virtual") << whitespace;
} }
void write_suffix_virtual(code_generator::output& output, const cpp_virtual& virt, void write_suffix_virtual(code_generator::output& output, const cpp_virtual& virt,
bool is_definition) bool is_definition)
{ {
if (is_definition) if (is_definition)
// don't include it in definition // don't include it in definition
return; return;
@ -659,10 +653,10 @@ namespace
output << whitespace << keyword("override"); output << whitespace << keyword("override");
if (is_final(virt)) if (is_final(virt))
output << whitespace << keyword("final"); output << whitespace << keyword("final");
} }
bool write_cv_ref(code_generator::output& output, const cpp_member_function_base& base) bool write_cv_ref(code_generator::output& output, const cpp_member_function_base& base)
{ {
auto need_ws = false; auto need_ws = false;
switch (base.cv_qualifier()) switch (base.cv_qualifier())
{ {
@ -697,13 +691,13 @@ namespace
} }
return need_ws; return need_ws;
} }
bool generate_member_function( bool generate_member_function(code_generator& generator, const cpp_member_function& func,
code_generator& generator, const cpp_member_function& func,
cpp_access_specifier_kind cur_access, cpp_access_specifier_kind cur_access,
type_safe::optional_ref<const cpp_template_specialization> spec = nullptr) type_safe::optional_ref<const cpp_template_specialization> spec
{ = nullptr)
{
code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access);
if (output) if (output)
{ {
@ -748,11 +742,11 @@ namespace
write_function_body(output, func, is_pure(func.virtual_info())); write_function_body(output, func, is_pure(func.virtual_info()));
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_conversion_op(code_generator& generator, const cpp_conversion_op& op, bool generate_conversion_op(code_generator& generator, const cpp_conversion_op& op,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(op), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(op), cur_access);
if (output) if (output)
{ {
@ -783,11 +777,11 @@ namespace
write_function_body(output, op, is_pure(op.virtual_info())); write_function_body(output, op, is_pure(op.virtual_info()));
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_constructor(code_generator& generator, const cpp_constructor& ctor, bool generate_constructor(code_generator& generator, const cpp_constructor& ctor,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(ctor), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(ctor), cur_access);
if (output) if (output)
{ {
@ -805,39 +799,38 @@ namespace
write_function_body(output, ctor, false); write_function_body(output, ctor, false);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_destructor(code_generator& generator, const cpp_destructor& dtor, bool generate_destructor(code_generator& generator, const cpp_destructor& dtor,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(dtor), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(dtor), cur_access);
if (output) if (output)
{ {
if (is_friended(dtor)) if (is_friended(dtor))
output << keyword("friend") << whitespace; output << keyword("friend") << whitespace;
write_prefix_virtual(output, dtor.virtual_info()); write_prefix_virtual(output, dtor.virtual_info());
output << identifier(dtor.semantic_scope()) << identifier(dtor.name()) output << identifier(dtor.semantic_scope()) << identifier(dtor.name()) << punctuation("(")
<< punctuation("(") << punctuation(")"); << punctuation(")");
write_noexcept(output, dtor, output.formatting().is_set(formatting_flags::operator_ws)); write_noexcept(output, dtor, output.formatting().is_set(formatting_flags::operator_ws));
write_suffix_virtual(output, dtor.virtual_info(), dtor.is_definition()); write_suffix_virtual(output, dtor.virtual_info(), dtor.is_definition());
write_function_body(output, dtor, is_pure(dtor.virtual_info())); write_function_body(output, dtor, is_pure(dtor.virtual_info()));
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_function_base(code_generator& generator, const cpp_function_base& base, bool generate_function_base(code_generator& generator, const cpp_function_base& base,
cpp_access_specifier_kind cur_access, cpp_access_specifier_kind cur_access,
const cpp_template_specialization& spec) const cpp_template_specialization& spec)
{ {
switch (base.kind()) switch (base.kind())
{ {
case cpp_entity_kind::function_t: case cpp_entity_kind::function_t:
return generate_function(generator, static_cast<const cpp_function&>(base), cur_access, return generate_function(generator, static_cast<const cpp_function&>(base), cur_access,
type_safe::ref(spec)); type_safe::ref(spec));
case cpp_entity_kind::member_function_t: case cpp_entity_kind::member_function_t:
return generate_member_function(generator, return generate_member_function(generator, static_cast<const cpp_member_function&>(base),
static_cast<const cpp_member_function&>(base),
cur_access, type_safe::ref(spec)); cur_access, type_safe::ref(spec));
case cpp_entity_kind::conversion_op_t: case cpp_entity_kind::conversion_op_t:
return generate_conversion_op(generator, static_cast<const cpp_conversion_op&>(base), return generate_conversion_op(generator, static_cast<const cpp_conversion_op&>(base),
@ -851,11 +844,11 @@ namespace
break; break;
} }
return false; return false;
} }
bool generate_friend(code_generator& generator, const cpp_friend& f, bool generate_friend(code_generator& generator, const cpp_friend& f,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(f), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(f), cur_access);
if (output) if (output)
{ {
@ -871,12 +864,12 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_template_type_parameter(code_generator& generator, bool generate_template_type_parameter(code_generator& generator,
const cpp_template_type_parameter& param, const cpp_template_type_parameter& param,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access);
if (output) if (output)
{ {
@ -892,12 +885,12 @@ namespace
} }
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_non_type_template_parameter(code_generator& generator, bool generate_non_type_template_parameter(code_generator& generator,
const cpp_non_type_template_parameter& param, const cpp_non_type_template_parameter& param,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access);
if (output) if (output)
{ {
@ -909,12 +902,12 @@ namespace
} }
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_template_template_parameter(code_generator& generator, bool generate_template_template_parameter(code_generator& generator,
const cpp_template_template_parameter& param, const cpp_template_template_parameter& param,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(param), cur_access);
if (output) if (output)
{ {
@ -930,11 +923,11 @@ namespace
<< param.default_template().value(); << param.default_template().value();
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
void write_template_parameters(code_generator::output& output, const cpp_template& templ, void write_template_parameters(code_generator::output& output, const cpp_template& templ,
bool hide_if_empty) bool hide_if_empty)
{ {
if (!hide_if_empty) if (!hide_if_empty)
output << keyword("template") << operator_ws << punctuation("<") << bracket_ws; output << keyword("template") << operator_ws << punctuation("<") << bracket_ws;
@ -958,11 +951,11 @@ namespace
if (!need_header) if (!need_header)
output << bracket_ws << punctuation(">") << newl; output << bracket_ws << punctuation(">") << newl;
} }
bool generate_alias_template(code_generator& generator, const cpp_alias_template& alias, bool generate_alias_template(code_generator& generator, const cpp_alias_template& alias,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(alias), cur_access);
if (output) if (output)
{ {
@ -970,11 +963,11 @@ namespace
generate_code_impl(generator, alias.type_alias(), cur_access); generate_code_impl(generator, alias.type_alias(), cur_access);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_variable_template(code_generator& generator, const cpp_variable_template& var, bool generate_variable_template(code_generator& generator, const cpp_variable_template& var,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access);
if (output) if (output)
{ {
@ -982,11 +975,11 @@ namespace
generate_code_impl(generator, var.variable(), cur_access); generate_code_impl(generator, var.variable(), cur_access);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_function_template(code_generator& generator, const cpp_function_template& func, bool generate_function_template(code_generator& generator, const cpp_function_template& func,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access);
if (output) if (output)
{ {
@ -994,12 +987,12 @@ namespace
generate_code_impl(generator, func.function(), cur_access); generate_code_impl(generator, func.function(), cur_access);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_function_template_specialization(code_generator& generator, bool generate_function_template_specialization(code_generator& generator,
const cpp_function_template_specialization& func, const cpp_function_template_specialization& func,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(func), cur_access);
if (output) if (output)
{ {
@ -1010,11 +1003,11 @@ namespace
generate_function_base(generator, func.function(), cur_access, func); generate_function_base(generator, func.function(), cur_access, func);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_class_template(code_generator& generator, const cpp_class_template& templ, bool generate_class_template(code_generator& generator, const cpp_class_template& templ,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(templ), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(templ), cur_access);
if (output) if (output)
{ {
@ -1022,12 +1015,12 @@ namespace
generate_class(generator, templ.class_(), cur_access); generate_class(generator, templ.class_(), cur_access);
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_class_template_specialization(code_generator& generator, bool generate_class_template_specialization(code_generator& generator,
const cpp_class_template_specialization& templ, const cpp_class_template_specialization& templ,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(templ), cur_access); code_generator::output output(type_safe::ref(generator), type_safe::ref(templ), cur_access);
if (output) if (output)
{ {
@ -1035,13 +1028,12 @@ namespace
generate_class(generator, templ.class_(), cur_access, type_safe::ref(templ)); generate_class(generator, templ.class_(), cur_access, type_safe::ref(templ));
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_static_assert(code_generator& generator, const cpp_static_assert& assert, bool generate_static_assert(code_generator& generator, const cpp_static_assert& assert,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(assert), code_generator::output output(type_safe::ref(generator), type_safe::ref(assert), cur_access);
cur_access);
if (output) if (output)
{ {
output << keyword("static_assert") << punctuation("(") << bracket_ws; output << keyword("static_assert") << punctuation("(") << bracket_ws;
@ -1050,24 +1042,23 @@ namespace
output << bracket_ws << punctuation(");") << newl; output << bracket_ws << punctuation(");") << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_unexposed(code_generator& generator, const cpp_unexposed_entity& entity, bool generate_unexposed(code_generator& generator, const cpp_unexposed_entity& entity,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
code_generator::output output(type_safe::ref(generator), type_safe::ref(entity), code_generator::output output(type_safe::ref(generator), type_safe::ref(entity), cur_access);
cur_access);
if (output) if (output)
{ {
detail::write_token_string(output, entity.spelling()); detail::write_token_string(output, entity.spelling());
output << newl; output << newl;
} }
return static_cast<bool>(output); return static_cast<bool>(output);
} }
bool generate_code_impl(code_generator& generator, const cpp_entity& e, bool generate_code_impl(code_generator& generator, const cpp_entity& e,
cpp_access_specifier_kind cur_access) cpp_access_specifier_kind cur_access)
{ {
switch (e.kind()) switch (e.kind())
{ {
#define CPPAST_DETAIL_HANDLE(Name) \ #define CPPAST_DETAIL_HANDLE(Name) \
@ -1133,7 +1124,7 @@ namespace
} }
return false; return false;
} }
} // namespace } // namespace
bool code_generator::generate_code(const cpp_entity& entity) bool code_generator::generate_code(const cpp_entity& entity)

View file

@ -12,8 +12,8 @@ using namespace cppast;
namespace namespace
{ {
const char* get_attribute_name(cpp_attribute_kind kind) noexcept const char* get_attribute_name(cpp_attribute_kind kind) noexcept
{ {
switch (kind) switch (kind)
{ {
case cpp_attribute_kind::alignas_: case cpp_attribute_kind::alignas_:
@ -36,8 +36,8 @@ namespace
} }
return "<error>"; return "<error>";
}
} }
} // namespace
cpp_attribute::cpp_attribute(cpp_attribute_kind kind, cpp_attribute::cpp_attribute(cpp_attribute_kind kind,
type_safe::optional<cpp_token_string> arguments) type_safe::optional<cpp_token_string> arguments)
@ -49,8 +49,8 @@ cpp_attribute::cpp_attribute(cpp_attribute_kind kind,
type_safe::optional_ref<const cpp_attribute> cppast::has_attribute( type_safe::optional_ref<const cpp_attribute> cppast::has_attribute(
const cpp_attribute_list& attributes, const std::string& name) const cpp_attribute_list& attributes, const std::string& name)
{ {
auto iter = auto iter
std::find_if(attributes.begin(), attributes.end(), [&](const cpp_attribute& attribute) { = std::find_if(attributes.begin(), attributes.end(), [&](const cpp_attribute& attribute) {
if (attribute.scope()) if (attribute.scope())
return attribute.scope().value() + "::" + attribute.name() == name; return attribute.scope().value() + "::" + attribute.name() == name;
else else
@ -66,8 +66,8 @@ type_safe::optional_ref<const cpp_attribute> cppast::has_attribute(
type_safe::optional_ref<const cpp_attribute> cppast::has_attribute( type_safe::optional_ref<const cpp_attribute> cppast::has_attribute(
const cpp_attribute_list& attributes, cpp_attribute_kind kind) const cpp_attribute_list& attributes, cpp_attribute_kind kind)
{ {
auto iter = auto iter
std::find_if(attributes.begin(), attributes.end(), = std::find_if(attributes.begin(), attributes.end(),
[&](const cpp_attribute& attribute) { return attribute.kind() == kind; }); [&](const cpp_attribute& attribute) { return attribute.kind() == kind; });
if (iter == attributes.end()) if (iter == attributes.end())

View file

@ -4,10 +4,10 @@
#include <cppast/cpp_class.hpp> #include <cppast/cpp_class.hpp>
#include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_alias_template.hpp> #include <cppast/cpp_alias_template.hpp>
#include <cppast/cpp_class_template.hpp> #include <cppast/cpp_class_template.hpp>
#include <cppast/cpp_entity_index.hpp>
#include <cppast/cpp_entity_kind.hpp>
using namespace cppast; using namespace cppast;
@ -103,8 +103,8 @@ cpp_entity_kind cpp_class::do_get_entity_kind() const noexcept
namespace namespace
{ {
cpp_entity_ref get_type_ref(const cpp_type& type) cpp_entity_ref get_type_ref(const cpp_type& type)
{ {
if (type.kind() == cpp_type_kind::user_defined_t) if (type.kind() == cpp_type_kind::user_defined_t)
{ {
auto& ref = static_cast<const cpp_user_defined_type&>(type).entity(); auto& ref = static_cast<const cpp_user_defined_type&>(type).entity();
@ -112,8 +112,7 @@ namespace
} }
else if (type.kind() == cpp_type_kind::template_instantiation_t) else if (type.kind() == cpp_type_kind::template_instantiation_t)
{ {
auto& ref = auto& ref = static_cast<const cpp_template_instantiation_type&>(type).primary_template();
static_cast<const cpp_template_instantiation_type&>(type).primary_template();
return cpp_entity_ref(ref.id()[0u], ref.name()); return cpp_entity_ref(ref.id()[0u], ref.name());
} }
@ -123,11 +122,11 @@ namespace
|| type.kind() == cpp_type_kind::unexposed_t, || type.kind() == cpp_type_kind::unexposed_t,
detail::assert_handler{}); detail::assert_handler{});
return cpp_entity_ref(cpp_entity_id("<null id>"), ""); return cpp_entity_ref(cpp_entity_id("<null id>"), "");
} }
type_safe::optional_ref<const cpp_entity> get_entity_impl(const cpp_entity_index& index, type_safe::optional_ref<const cpp_entity> get_entity_impl(const cpp_entity_index& index,
const cpp_entity_ref& ref) const cpp_entity_ref& ref)
{ {
auto result = ref.get(index); auto result = ref.get(index);
if (result.empty()) if (result.empty())
return nullptr; return nullptr;
@ -141,11 +140,11 @@ namespace
static_cast<const cpp_class_template_specialization&>(*entity).class_()); static_cast<const cpp_class_template_specialization&>(*entity).class_());
else else
return entity; return entity;
} }
type_safe::optional_ref<const cpp_class> get_class_impl(const cpp_entity_index& index, type_safe::optional_ref<const cpp_class> get_class_impl(const cpp_entity_index& index,
const cpp_entity_ref& ref) const cpp_entity_ref& ref)
{ {
auto entity = get_entity_impl(index, ref); auto entity = get_entity_impl(index, ref);
if (!entity) if (!entity)
return nullptr; return nullptr;
@ -165,8 +164,8 @@ namespace
DEBUG_ASSERT(entity.value().kind() == cpp_class::kind(), detail::assert_handler{}); DEBUG_ASSERT(entity.value().kind() == cpp_class::kind(), detail::assert_handler{});
return type_safe::ref(static_cast<const cpp_class&>(entity.value())); return type_safe::ref(static_cast<const cpp_class&>(entity.value()));
} }
}
} }
} // namespace
type_safe::optional_ref<const cpp_class> cppast::get_class(const cpp_entity_index& index, type_safe::optional_ref<const cpp_class> cppast::get_class(const cpp_entity_index& index,
const cpp_base_class& base) const cpp_base_class& base)

View file

@ -4,17 +4,16 @@
#include <cppast/cpp_entity_index.hpp> #include <cppast/cpp_entity_index.hpp>
#include <cppast/detail/assert.hpp>
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_kind.hpp> #include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_file.hpp> #include <cppast/cpp_file.hpp>
#include <cppast/detail/assert.hpp>
using namespace cppast; using namespace cppast;
cpp_entity_index::duplicate_definition_error::duplicate_definition_error() cpp_entity_index::duplicate_definition_error::duplicate_definition_error()
: std::logic_error("duplicate registration of entity definition") : std::logic_error("duplicate registration of entity definition")
{ {}
}
void cpp_entity_index::register_definition(cpp_entity_id id, void cpp_entity_index::register_definition(cpp_entity_id id,
type_safe::object_ref<const cpp_entity> entity) const type_safe::object_ref<const cpp_entity> entity) const

View file

@ -17,8 +17,8 @@ std::unique_ptr<cpp_enum_value> cpp_enum_value::build(const cpp_entity_index& id
std::string name, std::string name,
std::unique_ptr<cpp_expression> value) std::unique_ptr<cpp_expression> value)
{ {
auto result = auto result
std::unique_ptr<cpp_enum_value>(new cpp_enum_value(std::move(name), std::move(value))); = std::unique_ptr<cpp_enum_value>(new cpp_enum_value(std::move(name), std::move(value)));
idx.register_definition(std::move(id), type_safe::ref(*result)); idx.register_definition(std::move(id), type_safe::ref(*result));
return result; return result;
} }

View file

@ -8,8 +8,8 @@ using namespace cppast;
namespace namespace
{ {
void write_literal(code_generator::output& output, const cpp_literal_expression& expr) void write_literal(code_generator::output& output, const cpp_literal_expression& expr)
{ {
auto type_kind = cpp_void; auto type_kind = cpp_void;
if (expr.type().kind() == cpp_type_kind::builtin_t) if (expr.type().kind() == cpp_type_kind::builtin_t)
type_kind = static_cast<const cpp_builtin_type&>(expr.type()).builtin_type_kind(); type_kind = static_cast<const cpp_builtin_type&>(expr.type()).builtin_type_kind();
@ -71,14 +71,14 @@ namespace
output << keyword(expr.value()); output << keyword(expr.value());
break; break;
} }
}
void write_unexposed(code_generator::output& output, const cpp_unexposed_expression& expr)
{
detail::write_token_string(output, expr.expression());
}
} }
void write_unexposed(code_generator::output& output, const cpp_unexposed_expression& expr)
{
detail::write_token_string(output, expr.expression());
}
} // namespace
void detail::write_expression(code_generator::output& output, const cpp_expression& expr) void detail::write_expression(code_generator::output& output, const cpp_expression& expr)
{ {
switch (expr.kind()) switch (expr.kind())

View file

@ -15,8 +15,8 @@ using namespace cppast;
namespace namespace
{ {
type_safe::optional_ref<const cpp_forward_declarable> get_declarable(const cpp_entity& e) type_safe::optional_ref<const cpp_forward_declarable> get_declarable(const cpp_entity& e)
{ {
switch (e.kind()) switch (e.kind())
{ {
case cpp_entity_kind::enum_t: case cpp_entity_kind::enum_t:
@ -69,11 +69,11 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return nullptr; return nullptr;
} }
type_safe::optional_ref<const cpp_entity> get_definition_impl(const cpp_entity_index& idx, type_safe::optional_ref<const cpp_entity> get_definition_impl(const cpp_entity_index& idx,
const cpp_entity& e) const cpp_entity& e)
{ {
auto declarable = get_declarable(e); auto declarable = get_declarable(e);
if (!declarable || declarable.value().is_definition()) if (!declarable || declarable.value().is_definition())
// not declarable or is a definition // not declarable or is a definition
@ -81,7 +81,7 @@ namespace
return type_safe::ref(e); return type_safe::ref(e);
// else lookup definition // else lookup definition
return idx.lookup_definition(declarable.value().definition().value()); return idx.lookup_definition(declarable.value().definition().value());
} }
} // namespace } // namespace
bool cppast::is_definition(const cpp_entity& e) noexcept bool cppast::is_definition(const cpp_entity& e) noexcept

View file

@ -21,20 +21,20 @@ void cpp_token_string::builder::unmunch()
namespace namespace
{ {
template <std::size_t N> template <std::size_t N>
bool starts_with(const char* ptr, const char (&str)[N]) bool starts_with(const char* ptr, const char (&str)[N])
{ {
return std::strncmp(ptr, str, N - 1u) == 0; return std::strncmp(ptr, str, N - 1u) == 0;
} }
bool starts_with(const char* ptr, const std::string& str) bool starts_with(const char* ptr, const std::string& str)
{ {
return std::strncmp(ptr, str.c_str(), str.size()) == 0; return std::strncmp(ptr, str.c_str(), str.size()) == 0;
} }
template <std::size_t N> template <std::size_t N>
bool bump_if(const char*& ptr, const char (&str)[N]) bool bump_if(const char*& ptr, const char (&str)[N])
{ {
if (starts_with(ptr, str)) if (starts_with(ptr, str))
{ {
ptr += N - 1; ptr += N - 1;
@ -42,10 +42,10 @@ namespace
} }
else else
return false; return false;
} }
bool bump_if(const char*& ptr, const std::string& str) bool bump_if(const char*& ptr, const std::string& str)
{ {
if (starts_with(ptr, str)) if (starts_with(ptr, str))
{ {
ptr += str.size(); ptr += str.size();
@ -53,10 +53,10 @@ namespace
} }
else else
return false; return false;
} }
bool is_identifier_nondigit(char c) bool is_identifier_nondigit(char c)
{ {
// assume ASCII // assume ASCII
if (c >= 'a' && c <= 'z') if (c >= 'a' && c <= 'z')
return true; return true;
@ -67,20 +67,20 @@ namespace
else else
// technically \uXXX is allowed as well, but I haven't seen that used ever // technically \uXXX is allowed as well, but I haven't seen that used ever
return false; return false;
} }
bool is_digit(char c) bool is_digit(char c)
{ {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
bool is_hexadecimal_digit(char c) bool is_hexadecimal_digit(char c)
{ {
return is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); return is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
} }
type_safe::optional<std::string> bump_identifier(const char*& ptr) type_safe::optional<std::string> bump_identifier(const char*& ptr)
{ {
if (is_identifier_nondigit(*ptr)) if (is_identifier_nondigit(*ptr))
{ {
std::string result; std::string result;
@ -93,10 +93,10 @@ namespace
} }
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
type_safe::optional<cpp_token> identifier_token(const char*& ptr) type_safe::optional<cpp_token> identifier_token(const char*& ptr)
{ {
auto identifier = bump_identifier(ptr); auto identifier = bump_identifier(ptr);
if (!identifier) if (!identifier)
return type_safe::nullopt; return type_safe::nullopt;
@ -201,27 +201,27 @@ namespace
return cpp_token(cpp_token_kind::punctuation, "^="); return cpp_token(cpp_token_kind::punctuation, "^=");
else else
return cpp_token(cpp_token_kind::identifier, identifier.value()); return cpp_token(cpp_token_kind::identifier, identifier.value());
} }
void append_udl_suffix(std::string& literal, const char*& ptr) void append_udl_suffix(std::string& literal, const char*& ptr)
{ {
if (auto id = identifier_token(ptr)) if (auto id = identifier_token(ptr))
literal += id.value().spelling; literal += id.value().spelling;
} }
template <typename DigitPredicate> template <typename DigitPredicate>
std::string parse_digit_sequence(const char*& ptr, DigitPredicate is_digit) std::string parse_digit_sequence(const char*& ptr, DigitPredicate is_digit)
{ {
std::string result; std::string result;
for (; is_digit(*ptr) || *ptr == '\''; ++ptr) for (; is_digit(*ptr) || *ptr == '\''; ++ptr)
if (*ptr != '\'') if (*ptr != '\'')
result += *ptr; result += *ptr;
DEBUG_ASSERT(result.empty() || result.back() != '\'', detail::assert_handler{}); DEBUG_ASSERT(result.empty() || result.back() != '\'', detail::assert_handler{});
return result; return result;
} }
void append_integer_suffix(std::string& literal, const char*& ptr) void append_integer_suffix(std::string& literal, const char*& ptr)
{ {
auto append_unsigned_suffix = [](std::string& literal, const char*& ptr) { auto append_unsigned_suffix = [](std::string& literal, const char*& ptr) {
if (*ptr == 'u' || *ptr == 'U') if (*ptr == 'u' || *ptr == 'U')
{ {
@ -253,20 +253,20 @@ namespace
append_unsigned_suffix(literal, ptr); append_unsigned_suffix(literal, ptr);
else else
append_udl_suffix(literal, ptr); append_udl_suffix(literal, ptr);
} }
void append_floating_point_suffix(std::string& literal, const char*& ptr) void append_floating_point_suffix(std::string& literal, const char*& ptr)
{ {
if (*ptr == 'f' || *ptr == 'F') if (*ptr == 'f' || *ptr == 'F')
literal += *ptr++; literal += *ptr++;
else if (*ptr == 'l' || *ptr == 'L') else if (*ptr == 'l' || *ptr == 'L')
literal += *ptr++; literal += *ptr++;
else else
append_udl_suffix(literal, ptr); append_udl_suffix(literal, ptr);
} }
type_safe::optional<std::string> parse_floating_point_exponent(const char*& ptr) type_safe::optional<std::string> parse_floating_point_exponent(const char*& ptr)
{ {
if (*ptr == 'e' || *ptr == 'E' || *ptr == 'p' || *ptr == 'P') if (*ptr == 'e' || *ptr == 'E' || *ptr == 'p' || *ptr == 'P')
{ {
std::string result; std::string result;
@ -279,10 +279,10 @@ namespace
} }
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
type_safe::optional<cpp_token> numeric_literal_token(const char*& ptr) type_safe::optional<cpp_token> numeric_literal_token(const char*& ptr)
{ {
if (starts_with(ptr, "0b") || starts_with(ptr, "0B")) // binary integer literal if (starts_with(ptr, "0b") || starts_with(ptr, "0B")) // binary integer literal
{ {
std::string result; std::string result;
@ -368,10 +368,10 @@ namespace
} }
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
type_safe::optional<std::string> parse_encoding_prefix(const char*& ptr) type_safe::optional<std::string> parse_encoding_prefix(const char*& ptr)
{ {
if (bump_if(ptr, "u8")) if (bump_if(ptr, "u8"))
return "u8"; return "u8";
else if (bump_if(ptr, "u")) else if (bump_if(ptr, "u"))
@ -382,10 +382,10 @@ namespace
return "L"; return "L";
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
type_safe::optional<cpp_token> character_literal(const char*& ptr) type_safe::optional<cpp_token> character_literal(const char*& ptr)
{ {
auto save = ptr; auto save = ptr;
auto prefix = parse_encoding_prefix(ptr); auto prefix = parse_encoding_prefix(ptr);
if (*ptr != '\'') if (*ptr != '\'')
@ -411,10 +411,10 @@ namespace
append_udl_suffix(result, ptr); append_udl_suffix(result, ptr);
return cpp_token(cpp_token_kind::char_literal, result); return cpp_token(cpp_token_kind::char_literal, result);
} }
} }
type_safe::optional<cpp_token> string_literal(const char*& ptr) type_safe::optional<cpp_token> string_literal(const char*& ptr)
{ {
auto save = ptr; auto save = ptr;
auto prefix = parse_encoding_prefix(ptr); auto prefix = parse_encoding_prefix(ptr);
if (starts_with(ptr, "R\"")) if (starts_with(ptr, "R\""))
@ -468,10 +468,10 @@ namespace
ptr = save; ptr = save;
return type_safe::nullopt; return type_safe::nullopt;
} }
} }
type_safe::optional<cpp_token> digraph_token(const char*& ptr) type_safe::optional<cpp_token> digraph_token(const char*& ptr)
{ {
if (bump_if(ptr, "<%")) if (bump_if(ptr, "<%"))
return cpp_token(cpp_token_kind::punctuation, "{"); return cpp_token(cpp_token_kind::punctuation, "{");
else if (bump_if(ptr, "%>")) else if (bump_if(ptr, "%>"))
@ -489,10 +489,10 @@ namespace
return cpp_token(cpp_token_kind::punctuation, "#"); return cpp_token(cpp_token_kind::punctuation, "#");
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
type_safe::optional<cpp_token> punctuation_token(const char*& ptr) type_safe::optional<cpp_token> punctuation_token(const char*& ptr)
{ {
static constexpr const char* punctuations[] = { static constexpr const char* punctuations[] = {
// tokens staring with # // tokens staring with #
"##", "##",
@ -568,7 +568,7 @@ namespace
return cpp_token(cpp_token_kind::punctuation, punct); return cpp_token(cpp_token_kind::punctuation, punct);
return type_safe::nullopt; return type_safe::nullopt;
} }
} // namespace } // namespace
cpp_token_string cpp_token_string::tokenize(std::string str) cpp_token_string cpp_token_string::tokenize(std::string str)
@ -601,10 +601,10 @@ cpp_token_string cpp_token_string::tokenize(std::string str)
namespace namespace
{ {
bool is_identifier(char c) bool is_identifier(char c)
{ {
return std::isalnum(c) || c == '_'; return std::isalnum(c) || c == '_';
} }
} // namespace } // namespace
std::string cpp_token_string::as_string() const std::string cpp_token_string::as_string() const

View file

@ -10,8 +10,8 @@
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_kind.hpp> #include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_function_type.hpp> #include <cppast/cpp_function_type.hpp>
#include <cppast/cpp_type_alias.hpp>
#include <cppast/cpp_template.hpp> #include <cppast/cpp_template.hpp>
#include <cppast/cpp_type_alias.hpp>
using namespace cppast; using namespace cppast;
@ -174,10 +174,10 @@ std::unique_ptr<cpp_dependent_type> cpp_dependent_type::build(
namespace namespace
{ {
// is directly a complex type // is directly a complex type
// is_complex_type also checks for children // is_complex_type also checks for children
bool is_direct_complex(const cpp_type& type) noexcept bool is_direct_complex(const cpp_type& type) noexcept
{ {
switch (type.kind()) switch (type.kind())
{ {
case cpp_type_kind::builtin_t: case cpp_type_kind::builtin_t:
@ -203,7 +203,7 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return false; return false;
} }
} // namespace } // namespace
bool detail::is_complex_type(const cpp_type& type) noexcept bool detail::is_complex_type(const cpp_type& type) noexcept
@ -226,56 +226,55 @@ bool detail::is_complex_type(const cpp_type& type) noexcept
namespace namespace
{ {
void comma(const code_generator::output& output) void comma(const code_generator::output& output)
{ {
output << punctuation(","); output << punctuation(",");
if (output.formatting().is_set(formatting_flags::comma_ws)) if (output.formatting().is_set(formatting_flags::comma_ws))
output << whitespace; output << whitespace;
} }
void bracket_ws(const code_generator::output& output) void bracket_ws(const code_generator::output& output)
{ {
if (output.formatting().is_set(formatting_flags::bracket_ws)) if (output.formatting().is_set(formatting_flags::bracket_ws))
output << whitespace; output << whitespace;
} }
void operator_ws(const code_generator::output& output) void operator_ws(const code_generator::output& output)
{ {
if (output.formatting().is_set(formatting_flags::operator_ws)) if (output.formatting().is_set(formatting_flags::operator_ws))
output << whitespace; output << whitespace;
} }
void write_builtin(code_generator::output& output, const cpp_builtin_type& type) void write_builtin(code_generator::output& output, const cpp_builtin_type& type)
{ {
output << keyword(to_string(type.builtin_type_kind())); output << keyword(to_string(type.builtin_type_kind()));
} }
void write_user_defined(code_generator::output& output, const cpp_user_defined_type& type) void write_user_defined(code_generator::output& output, const cpp_user_defined_type& type)
{ {
output << type.entity(); output << type.entity();
} }
void write_auto(code_generator::output& output, const cpp_auto_type&) void write_auto(code_generator::output& output, const cpp_auto_type&)
{ {
output << keyword("auto"); output << keyword("auto");
} }
void write_decltype(code_generator::output& output, const cpp_decltype_type& type) void write_decltype(code_generator::output& output, const cpp_decltype_type& type)
{ {
output << keyword("decltype") << punctuation("(") << bracket_ws; output << keyword("decltype") << punctuation("(") << bracket_ws;
detail::write_expression(output, type.expression()); detail::write_expression(output, type.expression());
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
} }
void write_decltype_auto(code_generator::output& output, const cpp_decltype_auto_type&) void write_decltype_auto(code_generator::output& output, const cpp_decltype_auto_type&)
{ {
output << keyword("decltype") << punctuation("(") << bracket_ws << keyword("auto") output << keyword("decltype") << punctuation("(") << bracket_ws << keyword("auto") << bracket_ws
<< bracket_ws << punctuation(")"); << punctuation(")");
} }
void write_cv_qualified_prefix(code_generator::output& output, void write_cv_qualified_prefix(code_generator::output& output, const cpp_cv_qualified_type& type)
const cpp_cv_qualified_type& type) {
{
detail::write_type_prefix(output, type.type()); detail::write_type_prefix(output, type.type());
if (is_direct_complex(type.type())) if (is_direct_complex(type.type()))
@ -285,24 +284,23 @@ namespace
output << whitespace << keyword("const"); output << whitespace << keyword("const");
if (is_volatile(type.cv_qualifier())) if (is_volatile(type.cv_qualifier()))
output << whitespace << keyword("volatile"); output << whitespace << keyword("volatile");
} }
void write_cv_qualified_suffix(code_generator::output& output, void write_cv_qualified_suffix(code_generator::output& output, const cpp_cv_qualified_type& type)
const cpp_cv_qualified_type& type) {
{
if (is_direct_complex(type.type())) if (is_direct_complex(type.type()))
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
detail::write_type_suffix(output, type.type()); detail::write_type_suffix(output, type.type());
} }
bool pointer_requires_paren(const cpp_pointer_type& type) bool pointer_requires_paren(const cpp_pointer_type& type)
{ {
auto kind = type.pointee().kind(); auto kind = type.pointee().kind();
return kind == cpp_type_kind::function_t || kind == cpp_type_kind::array_t; return kind == cpp_type_kind::function_t || kind == cpp_type_kind::array_t;
} }
void write_pointer_prefix(code_generator::output& output, const cpp_pointer_type& type) void write_pointer_prefix(code_generator::output& output, const cpp_pointer_type& type)
{ {
detail::write_type_prefix(output, type.pointee()); detail::write_type_prefix(output, type.pointee());
if (pointer_requires_paren(type)) if (pointer_requires_paren(type))
@ -311,17 +309,17 @@ namespace
output << whitespace; output << whitespace;
output << punctuation("*"); output << punctuation("*");
} }
void write_pointer_suffix(code_generator::output& output, const cpp_pointer_type& type) void write_pointer_suffix(code_generator::output& output, const cpp_pointer_type& type)
{ {
if (pointer_requires_paren(type)) if (pointer_requires_paren(type))
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
detail::write_type_suffix(output, type.pointee()); detail::write_type_suffix(output, type.pointee());
} }
void write_reference_prefix(code_generator::output& output, const cpp_reference_type& type) void write_reference_prefix(code_generator::output& output, const cpp_reference_type& type)
{ {
detail::write_type_prefix(output, type.referee()); detail::write_type_prefix(output, type.referee());
if (is_direct_complex(type.referee())) if (is_direct_complex(type.referee()))
@ -335,22 +333,22 @@ namespace
output << punctuation("&&"); output << punctuation("&&");
else else
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
} }
void write_reference_suffix(code_generator::output& output, const cpp_reference_type& type) void write_reference_suffix(code_generator::output& output, const cpp_reference_type& type)
{ {
if (is_direct_complex(type.referee())) if (is_direct_complex(type.referee()))
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
detail::write_type_suffix(output, type.referee()); detail::write_type_suffix(output, type.referee());
} }
void write_array_prefix(code_generator::output& output, const cpp_array_type& type) void write_array_prefix(code_generator::output& output, const cpp_array_type& type)
{ {
detail::write_type_prefix(output, type.value_type()); detail::write_type_prefix(output, type.value_type());
} }
void write_array_suffix(code_generator::output& output, const cpp_array_type& type) void write_array_suffix(code_generator::output& output, const cpp_array_type& type)
{ {
output << punctuation("["); output << punctuation("[");
if (type.size()) if (type.size())
{ {
@ -360,16 +358,16 @@ namespace
} }
output << punctuation("]"); output << punctuation("]");
detail::write_type_suffix(output, type.value_type()); detail::write_type_suffix(output, type.value_type());
} }
void write_function_prefix(code_generator::output& output, const cpp_function_type& type) void write_function_prefix(code_generator::output& output, const cpp_function_type& type)
{ {
detail::write_type_prefix(output, type.return_type()); detail::write_type_prefix(output, type.return_type());
} }
template <typename T> template <typename T>
void write_parameters(code_generator::output& output, const T& type) void write_parameters(code_generator::output& output, const T& type)
{ {
output << punctuation("(") << bracket_ws; output << punctuation("(") << bracket_ws;
auto need_sep = false; auto need_sep = false;
@ -390,17 +388,17 @@ namespace
} }
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
} }
void write_function_suffix(code_generator::output& output, const cpp_function_type& type) void write_function_suffix(code_generator::output& output, const cpp_function_type& type)
{ {
write_parameters(output, type); write_parameters(output, type);
detail::write_type_suffix(output, type.return_type()); detail::write_type_suffix(output, type.return_type());
} }
const cpp_type& strip_class_type(const cpp_type& type, cpp_cv* cv, cpp_reference* ref) const cpp_type& strip_class_type(const cpp_type& type, cpp_cv* cv, cpp_reference* ref)
{ {
if (type.kind() == cpp_type_kind::cv_qualified_t) if (type.kind() == cpp_type_kind::cv_qualified_t)
{ {
auto& cv_qual = static_cast<const cpp_cv_qualified_type&>(type); auto& cv_qual = static_cast<const cpp_cv_qualified_type&>(type);
@ -420,21 +418,21 @@ namespace
DEBUG_ASSERT(!detail::is_complex_type(type), detail::assert_handler{}); DEBUG_ASSERT(!detail::is_complex_type(type), detail::assert_handler{});
return type; return type;
} }
} }
void write_member_function_prefix(code_generator::output& output, void write_member_function_prefix(code_generator::output& output,
const cpp_member_function_type& type) const cpp_member_function_type& type)
{ {
detail::write_type_prefix(output, type.return_type()); detail::write_type_prefix(output, type.return_type());
output << punctuation("(") << bracket_ws; output << punctuation("(") << bracket_ws;
detail::write_type_prefix(output, strip_class_type(type.class_type(), nullptr, nullptr)); detail::write_type_prefix(output, strip_class_type(type.class_type(), nullptr, nullptr));
output << punctuation("::"); output << punctuation("::");
} }
void write_member_function_suffix(code_generator::output& output, void write_member_function_suffix(code_generator::output& output,
const cpp_member_function_type& type) const cpp_member_function_type& type)
{ {
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
write_parameters(output, type); write_parameters(output, type);
@ -455,32 +453,31 @@ namespace
output << operator_ws << punctuation("&&") << operator_ws; output << operator_ws << punctuation("&&") << operator_ws;
detail::write_type_suffix(output, type.return_type()); detail::write_type_suffix(output, type.return_type());
} }
void write_member_object_prefix(code_generator::output& output, void write_member_object_prefix(code_generator::output& output, const cpp_member_object_type& type)
const cpp_member_object_type& type) {
{
detail::write_type_prefix(output, type.object_type()); detail::write_type_prefix(output, type.object_type());
output << punctuation("(") << bracket_ws; output << punctuation("(") << bracket_ws;
DEBUG_ASSERT(!detail::is_complex_type(type.class_type()), detail::assert_handler{}); DEBUG_ASSERT(!detail::is_complex_type(type.class_type()), detail::assert_handler{});
detail::write_type_prefix(output, type.class_type()); detail::write_type_prefix(output, type.class_type());
output << punctuation("::"); output << punctuation("::");
} }
void write_member_object_suffix(code_generator::output& output, const cpp_member_object_type&) void write_member_object_suffix(code_generator::output& output, const cpp_member_object_type&)
{ {
output << bracket_ws << punctuation(")"); output << bracket_ws << punctuation(")");
} }
void write_template_parameter(code_generator::output& output, void write_template_parameter(code_generator::output& output,
const cpp_template_parameter_type& type) const cpp_template_parameter_type& type)
{ {
output << type.entity(); output << type.entity();
} }
void write_template_instantiation(code_generator::output& output, void write_template_instantiation(code_generator::output& output,
const cpp_template_instantiation_type& type) const cpp_template_instantiation_type& type)
{ {
output << type.primary_template(); output << type.primary_template();
if (output.was_reference_excluded()) if (output.was_reference_excluded())
return; return;
@ -490,17 +487,17 @@ namespace
else else
output << punctuation("<") << bracket_ws << token_seq(type.unexposed_arguments()) output << punctuation("<") << bracket_ws << token_seq(type.unexposed_arguments())
<< bracket_ws << punctuation(">"); << bracket_ws << punctuation(">");
} }
void write_dependent(code_generator::output& output, const cpp_dependent_type& type) void write_dependent(code_generator::output& output, const cpp_dependent_type& type)
{ {
output << token_seq(type.name()); output << token_seq(type.name());
} }
void write_unexposed(code_generator::output& output, const cpp_unexposed_type& type) void write_unexposed(code_generator::output& output, const cpp_unexposed_type& type)
{ {
output << token_seq(type.name()); output << token_seq(type.name());
} }
} // namespace } // namespace
void detail::write_type_prefix(code_generator::output& output, const cpp_type& type) void detail::write_type_prefix(code_generator::output& output, const cpp_type& type)

View file

@ -2,8 +2,8 @@
// This file is subject to the license terms in the LICENSE file // This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution. // found in the top-level directory of this distribution.
#include <cppast/cpp_class.hpp>
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <cppast/cpp_class.hpp>
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"
#include "parse_functions.hpp" #include "parse_functions.hpp"
@ -12,8 +12,8 @@ using namespace cppast;
namespace namespace
{ {
cpp_class_kind parse_class_kind(detail::cxtoken_stream& stream) cpp_class_kind parse_class_kind(detail::cxtoken_stream& stream)
{ {
auto kind = clang_getTemplateCursorKind(stream.cursor()); auto kind = clang_getTemplateCursorKind(stream.cursor());
if (kind == CXCursor_NoDeclFound) if (kind == CXCursor_NoDeclFound)
kind = clang_getCursorKind(stream.cursor()); kind = clang_getCursorKind(stream.cursor());
@ -44,10 +44,10 @@ namespace
} }
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return cpp_class_kind::class_t; return cpp_class_kind::class_t;
} }
cpp_class::builder make_class_builder(const detail::parse_context& context, const CXCursor& cur) cpp_class::builder make_class_builder(const detail::parse_context& context, const CXCursor& cur)
{ {
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
detail::cxtoken_stream stream(tokenizer, cur); detail::cxtoken_stream stream(tokenizer, cur);
@ -58,10 +58,10 @@ namespace
auto result = cpp_class::builder(name.c_str(), kind); auto result = cpp_class::builder(name.c_str(), kind);
result.get().add_attribute(attributes); result.get().add_attribute(attributes);
return result; return result;
} }
cpp_access_specifier_kind convert_access(const CXCursor& cur) cpp_access_specifier_kind convert_access(const CXCursor& cur)
{ {
switch (clang_getCXXAccessSpecifier(cur)) switch (clang_getCXXAccessSpecifier(cur))
{ {
case CX_CXXInvalidAccessSpecifier: case CX_CXXInvalidAccessSpecifier:
@ -77,17 +77,17 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return cpp_public; return cpp_public;
} }
void add_access_specifier(cpp_class::builder& builder, const CXCursor& cur) void add_access_specifier(cpp_class::builder& builder, const CXCursor& cur)
{ {
DEBUG_ASSERT(cur.kind == CXCursor_CXXAccessSpecifier, detail::assert_handler{}); DEBUG_ASSERT(cur.kind == CXCursor_CXXAccessSpecifier, detail::assert_handler{});
builder.access_specifier(convert_access(cur)); builder.access_specifier(convert_access(cur));
} }
void add_base_class(cpp_class::builder& builder, const detail::parse_context& context, void add_base_class(cpp_class::builder& builder, const detail::parse_context& context,
const CXCursor& cur, const CXCursor& class_cur) const CXCursor& cur, const CXCursor& class_cur)
{ {
DEBUG_ASSERT(cur.kind == CXCursor_CXXBaseSpecifier, detail::assert_handler{}); DEBUG_ASSERT(cur.kind == CXCursor_CXXBaseSpecifier, detail::assert_handler{});
auto access = convert_access(cur); auto access = convert_access(cur);
auto is_virtual = clang_isVirtualBase(cur) != 0u; auto is_virtual = clang_isVirtualBase(cur) != 0u;
@ -107,8 +107,8 @@ namespace
auto type = detail::parse_type(context, class_cur, clang_getCursorType(cur)); auto type = detail::parse_type(context, class_cur, clang_getCursorType(cur));
auto& base = builder.base_class(std::move(name), std::move(type), access, is_virtual); auto& base = builder.base_class(std::move(name), std::move(type), access, is_virtual);
base.add_attribute(attributes); base.add_attribute(attributes);
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context& context,
const CXCursor& cur, const CXCursor& parent_cur) const CXCursor& cur, const CXCursor& parent_cur)
@ -145,8 +145,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
stream.bump(); stream.bump();
} }
if (!scope.empty()) if (!scope.empty())
semantic_parent = semantic_parent
cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)), = cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
std::move(scope)); std::move(scope));
} }
@ -159,12 +159,12 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
add_base_class(builder, context, child, cur); add_base_class(builder, context, child, cur);
else if (kind == CXCursor_CXXFinalAttr) else if (kind == CXCursor_CXXFinalAttr)
builder.is_final(); builder.is_final();
else if ( else if (kind == CXCursor_TemplateTypeParameter
kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter || kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_TemplateTemplateParameter || kind == CXCursor_ParmDecl || kind == CXCursor_TemplateTemplateParameter || kind == CXCursor_ParmDecl
|| clang_isExpression(kind) || clang_isReference(kind) || clang_isExpression(kind) || clang_isReference(kind)
|| kind || kind == CXCursor_UnexposedAttr) // I have no idea what this is, but happens
== CXCursor_UnexposedAttr) // I have no idea what this is, but happens on Windows // on Windows
// other children due to templates and stuff // other children due to templates and stuff
return; return;
else if (auto entity = parse_entity(context, &builder.get(), child)) else if (auto entity = parse_entity(context, &builder.get(), child))
@ -173,10 +173,10 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
} }
if (!is_friend && clang_isCursorDefinition(cur)) if (!is_friend && clang_isCursorDefinition(cur))
return is_templated ? return is_templated
builder.finish(std::move(semantic_parent)) : ? builder.finish(std::move(semantic_parent))
builder.finish(*context.idx, get_entity_id(cur), std::move(semantic_parent)); : builder.finish(*context.idx, get_entity_id(cur), std::move(semantic_parent));
else else
return is_templated ? builder.finish_declaration(detail::get_entity_id(cur)) : return is_templated ? builder.finish_declaration(detail::get_entity_id(cur))
builder.finish_declaration(*context.idx, get_entity_id(cur)); : builder.finish_declaration(*context.idx, get_entity_id(cur));
} }

View file

@ -13,21 +13,20 @@ using namespace cppast;
detail::cxtoken::cxtoken(const CXTranslationUnit& tu_unit, const CXToken& token) detail::cxtoken::cxtoken(const CXTranslationUnit& tu_unit, const CXToken& token)
: value_(clang_getTokenSpelling(tu_unit, token)), kind_(clang_getTokenKind(token)) : value_(clang_getTokenSpelling(tu_unit, token)), kind_(clang_getTokenKind(token))
{ {}
}
namespace namespace
{ {
bool cursor_is_function(CXCursorKind kind) bool cursor_is_function(CXCursorKind kind)
{ {
return kind == CXCursor_FunctionDecl || kind == CXCursor_CXXMethod return kind == CXCursor_FunctionDecl || kind == CXCursor_CXXMethod
|| kind == CXCursor_Constructor || kind == CXCursor_Destructor || kind == CXCursor_Constructor || kind == CXCursor_Destructor
|| kind == CXCursor_ConversionFunction; || kind == CXCursor_ConversionFunction;
} }
CXSourceLocation get_next_location(const CXTranslationUnit& tu, CXFile file, CXSourceLocation get_next_location(const CXTranslationUnit& tu, CXFile file,
const CXSourceLocation& loc, int inc = 1) const CXSourceLocation& loc, int inc = 1)
{ {
unsigned offset; unsigned offset;
clang_getSpellingLocation(loc, nullptr, nullptr, nullptr, &offset); clang_getSpellingLocation(loc, nullptr, nullptr, nullptr, &offset);
if (inc >= 0) if (inc >= 0)
@ -35,11 +34,11 @@ namespace
else else
offset -= unsigned(-inc); offset -= unsigned(-inc);
return clang_getLocationForOffset(tu, file, offset); return clang_getLocationForOffset(tu, file, offset);
} }
class simple_tokenizer class simple_tokenizer
{ {
public: public:
explicit simple_tokenizer(const CXTranslationUnit& tu, const CXSourceRange& range) : tu_(tu) explicit simple_tokenizer(const CXTranslationUnit& tu, const CXSourceRange& range) : tu_(tu)
{ {
clang_tokenize(tu, range, &tokens_, &no_); clang_tokenize(tu, range, &tokens_, &no_);
@ -63,35 +62,35 @@ namespace
return tokens_[i]; return tokens_[i];
} }
private: private:
CXTranslationUnit tu_; CXTranslationUnit tu_;
CXToken* tokens_; CXToken* tokens_;
unsigned no_; unsigned no_;
}; };
bool token_after_is(const CXTranslationUnit& tu, const CXFile& file, bool token_after_is(const CXTranslationUnit& tu, const CXFile& file, const CXSourceLocation& loc,
const CXSourceLocation& loc, const char* token_str, int inc) const char* token_str, int inc)
{ {
auto loc_after = get_next_location(tu, file, loc, inc); auto loc_after = get_next_location(tu, file, loc, inc);
if (!clang_Location_isFromMainFile(loc_after)) if (!clang_Location_isFromMainFile(loc_after))
return false; return false;
simple_tokenizer tokenizer(tu, inc > 0 ? clang_getRange(loc, loc_after) : simple_tokenizer tokenizer(tu, inc > 0 ? clang_getRange(loc, loc_after)
clang_getRange(loc_after, loc)); : clang_getRange(loc_after, loc));
if (tokenizer.size() == 0u) if (tokenizer.size() == 0u)
return false; return false;
detail::cxstring spelling(clang_getTokenSpelling(tu, tokenizer[0u])); detail::cxstring spelling(clang_getTokenSpelling(tu, tokenizer[0u]));
return spelling == token_str; return spelling == token_str;
} }
// clang_getCursorExtent() is somehow broken in various ways // clang_getCursorExtent() is somehow broken in various ways
// this function returns the actual CXSourceRange that covers all parts required for parsing // this function returns the actual CXSourceRange that covers all parts required for parsing
// might include more tokens // might include more tokens
// this function is the reason you shouldn't use libclang // this function is the reason you shouldn't use libclang
CXSourceRange get_extent(const CXTranslationUnit& tu, const CXFile& file, const CXCursor& cur, CXSourceRange get_extent(const CXTranslationUnit& tu, const CXFile& file, const CXCursor& cur,
bool& unmunch) bool& unmunch)
{ {
unmunch = false; unmunch = false;
auto extent = clang_getCursorExtent(cur); auto extent = clang_getCursorExtent(cur);
@ -103,8 +102,7 @@ namespace
|| kind == CXCursor_VarDecl || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl || kind == CXCursor_VarDecl || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl
|| kind == CXCursor_NonTypeTemplateParameter) || kind == CXCursor_NonTypeTemplateParameter)
{ {
if (token_after_is(tu, file, begin, "]", -2) if (token_after_is(tu, file, begin, "]", -2) && token_after_is(tu, file, begin, "]", -3))
&& token_after_is(tu, file, begin, "]", -3))
{ {
while (!token_after_is(tu, file, begin, "[", -1) while (!token_after_is(tu, file, begin, "[", -1)
&& !token_after_is(tu, file, begin, "[", -2)) && !token_after_is(tu, file, begin, "[", -2))
@ -112,8 +110,8 @@ namespace
begin = get_next_location(tu, file, begin, -3); begin = get_next_location(tu, file, begin, -3);
DEBUG_ASSERT(token_after_is(tu, file, begin, "[", 0) DEBUG_ASSERT(token_after_is(tu, file, begin, "[", 0)
&& token_after_is(tu, file, get_next_location(tu, file, begin), && token_after_is(tu, file, get_next_location(tu, file, begin), "[",
"[", 0), 0),
detail::parse_error_handler{}, cur, detail::parse_error_handler{}, cur,
"error in pre-function attribute parsing"); "error in pre-function attribute parsing");
} }
@ -207,8 +205,7 @@ namespace
end = next; end = next;
#endif #endif
} }
else if (kind == CXCursor_TemplateTemplateParameter else if (kind == CXCursor_TemplateTemplateParameter && token_after_is(tu, file, end, "<", 0))
&& token_after_is(tu, file, end, "<", 0))
{ {
// if you have a template template parameter in a template template parameter, // if you have a template template parameter in a template template parameter,
// the tokens are all messed up, only contain the `template` // the tokens are all messed up, only contain the `template`
@ -228,14 +225,12 @@ namespace
// second: skip until end of parameter // second: skip until end of parameter
// no need to handle default, so look for '>' or ',' // no need to handle default, so look for '>' or ','
while (!token_after_is(tu, file, next, ">", 0) while (!token_after_is(tu, file, next, ">", 0) && !token_after_is(tu, file, next, ",", 0))
&& !token_after_is(tu, file, next, ",", 0))
next = get_next_location(tu, file, next); next = get_next_location(tu, file, next);
// now we found the proper end of the token // now we found the proper end of the token
end = get_next_location(tu, file, next, -1); end = get_next_location(tu, file, next, -1);
} }
else if ((kind == CXCursor_TemplateTypeParameter else if ((kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_TemplateTemplateParameter) || kind == CXCursor_TemplateTemplateParameter)
&& token_after_is(tu, file, end, "...", 0)) && token_after_is(tu, file, end, "...", 0))
{ {
@ -246,16 +241,13 @@ namespace
// this should all go away once I redid the whole token thing... // this should all go away once I redid the whole token thing...
end = get_next_location(tu, file, end, 1); end = get_next_location(tu, file, end, 1);
DEBUG_ASSERT(token_after_is(tu, file, end, ">", 0) DEBUG_ASSERT(token_after_is(tu, file, end, ">", 0) || token_after_is(tu, file, end, ",", 0),
|| token_after_is(tu, file, end, ",", 0),
detail::parse_error_handler{}, cur, detail::parse_error_handler{}, cur,
"unexpected token in variadic parameter workaround"); "unexpected token in variadic parameter workaround");
} }
else if ((kind == CXCursor_TemplateTypeParameter else if ((kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_TemplateTemplateParameter) || kind == CXCursor_TemplateTemplateParameter)
&& !token_after_is(tu, file, end, ">", 0) && !token_after_is(tu, file, end, ">", 0) && !token_after_is(tu, file, end, ",", 0))
&& !token_after_is(tu, file, end, ",", 0))
{ {
DEBUG_ASSERT(token_after_is(tu, file, get_next_location(tu, file, end, -2), ">>", 0), DEBUG_ASSERT(token_after_is(tu, file, get_next_location(tu, file, end, -2), ">>", 0),
detail::parse_error_handler{}, cur, detail::parse_error_handler{}, cur,
@ -296,7 +288,7 @@ namespace
} }
return clang_getRange(begin, end); return clang_getRange(begin, end);
} }
} // namespace } // namespace
detail::cxtokenizer::cxtokenizer(const CXTranslationUnit& tu, const CXFile& file, detail::cxtokenizer::cxtokenizer(const CXTranslationUnit& tu, const CXFile& file,
@ -326,15 +318,15 @@ void detail::skip(detail::cxtoken_stream& stream, const char* str)
namespace namespace
{ {
bool starts_with(const char*& str, const detail::cxtoken& t) bool starts_with(const char*& str, const detail::cxtoken& t)
{ {
if (std::strncmp(str, t.c_str(), t.value().length()) != 0) if (std::strncmp(str, t.c_str(), t.value().length()) != 0)
return false; return false;
str += t.value().length(); str += t.value().length();
while (*str == ' ' || *str == '\t') while (*str == ' ' || *str == '\t')
++str; ++str;
return true; return true;
} }
} // namespace } // namespace
bool detail::skip_if(detail::cxtoken_stream& stream, const char* str, bool multi_token) bool detail::skip_if(detail::cxtoken_stream& stream, const char* str, bool multi_token)
@ -359,16 +351,16 @@ bool detail::skip_if(detail::cxtoken_stream& stream, const char* str, bool multi
namespace namespace
{ {
// whether or not the current angle bracket can be a comparison // whether or not the current angle bracket can be a comparison
// note: this is a heuristic I hope works often enough // note: this is a heuristic I hope works often enough
bool is_comparison(CXTokenKind last_kind, const detail::cxtoken& cur, CXTokenKind next_kind) bool is_comparison(CXTokenKind last_kind, const detail::cxtoken& cur, CXTokenKind next_kind)
{ {
if (cur == "<") if (cur == "<")
return last_kind == CXToken_Literal; return last_kind == CXToken_Literal;
else if (cur == ">") else if (cur == ">")
return next_kind == CXToken_Literal; return next_kind == CXToken_Literal;
return false; return false;
} }
} // namespace } // namespace
detail::cxtoken_iterator detail::find_closing_bracket(detail::cxtoken_stream stream) detail::cxtoken_iterator detail::find_closing_bracket(detail::cxtoken_stream stream)
@ -430,8 +422,8 @@ void detail::skip_brackets(detail::cxtoken_stream& stream)
namespace namespace
{ {
type_safe::optional<std::string> parse_attribute_using(detail::cxtoken_stream& stream) type_safe::optional<std::string> parse_attribute_using(detail::cxtoken_stream& stream)
{ {
// using identifier : // using identifier :
if (skip_if(stream, "using")) if (skip_if(stream, "using"))
{ {
@ -444,10 +436,10 @@ namespace
} }
else else
return type_safe::nullopt; return type_safe::nullopt;
} }
cpp_attribute_kind get_attribute_kind(const std::string& name) cpp_attribute_kind get_attribute_kind(const std::string& name)
{ {
if (name == "carries_dependency") if (name == "carries_dependency")
return cpp_attribute_kind::carries_dependency; return cpp_attribute_kind::carries_dependency;
else if (name == "deprecated") else if (name == "deprecated")
@ -462,10 +454,10 @@ namespace
return cpp_attribute_kind::noreturn; return cpp_attribute_kind::noreturn;
else else
return cpp_attribute_kind::unknown; return cpp_attribute_kind::unknown;
} }
cpp_token_string parse_attribute_arguments(detail::cxtoken_stream& stream) cpp_token_string parse_attribute_arguments(detail::cxtoken_stream& stream)
{ {
auto end = find_closing_bracket(stream); auto end = find_closing_bracket(stream);
skip(stream, "("); skip(stream, "(");
@ -475,11 +467,11 @@ namespace
skip(stream, ")"); skip(stream, ")");
return arguments; return arguments;
} }
cpp_attribute parse_attribute_token(detail::cxtoken_stream& stream, cpp_attribute parse_attribute_token(detail::cxtoken_stream& stream,
type_safe::optional<std::string> scope) type_safe::optional<std::string> scope)
{ {
// (identifier ::)_opt identifier ( '(' some tokens ')' )_opt ..._opt // (identifier ::)_opt identifier ( '(' some tokens ')' )_opt ..._opt
// parse name // parse name
@ -513,12 +505,11 @@ namespace
if (!scope && kind != cpp_attribute_kind::unknown) if (!scope && kind != cpp_attribute_kind::unknown)
return cpp_attribute(kind, std::move(arguments)); return cpp_attribute(kind, std::move(arguments));
else else
return cpp_attribute(std::move(scope), std::move(name), std::move(arguments), return cpp_attribute(std::move(scope), std::move(name), std::move(arguments), is_variadic);
is_variadic); }
}
bool parse_attribute_impl(cpp_attribute_list& result, detail::cxtoken_stream& stream) bool parse_attribute_impl(cpp_attribute_list& result, detail::cxtoken_stream& stream)
{ {
if (skip_if(stream, "[") && stream.peek() == "[") if (skip_if(stream, "[") && stream.peek() == "[")
{ {
// C++11 attribute // C++11 attribute
@ -584,7 +575,7 @@ namespace
} }
return false; return false;
} }
} // namespace } // namespace
cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway) cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway)
@ -602,8 +593,8 @@ cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool
namespace namespace
{ {
cpp_token_kind get_kind(const detail::cxtoken& token) cpp_token_kind get_kind(const detail::cxtoken& token)
{ {
switch (token.kind()) switch (token.kind())
{ {
case CXToken_Punctuation: case CXToken_Punctuation:
@ -632,7 +623,7 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return cpp_token_kind::punctuation; return cpp_token_kind::punctuation;
} }
} // namespace } // namespace
cpp_token_string detail::to_string(cxtoken_stream& stream, cxtoken_iterator end) cpp_token_string detail::to_string(cxtoken_stream& stream, cxtoken_iterator end)

View file

@ -15,8 +15,8 @@
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
class cxtoken class cxtoken
{ {
public: public:
@ -67,8 +67,7 @@ namespace cppast
class cxtokenizer class cxtokenizer
{ {
public: public:
explicit cxtokenizer(const CXTranslationUnit& tu, const CXFile& file, explicit cxtokenizer(const CXTranslationUnit& tu, const CXFile& file, const CXCursor& cur);
const CXCursor& cur);
cxtoken_iterator begin() const noexcept cxtoken_iterator begin() const noexcept
{ {
@ -97,13 +96,9 @@ namespace cppast
{ {
public: public:
explicit cxtoken_stream(const cxtokenizer& tokenizer, const CXCursor& cur) explicit cxtoken_stream(const cxtokenizer& tokenizer, const CXCursor& cur)
: cursor_(cur), : cursor_(cur), begin_(tokenizer.begin()), cur_(begin_), end_(tokenizer.end()),
begin_(tokenizer.begin()),
cur_(begin_),
end_(tokenizer.end()),
unmunch_(tokenizer.unmunch()) unmunch_(tokenizer.unmunch())
{ {}
}
const cxtoken& peek() const noexcept const cxtoken& peek() const noexcept
{ {
@ -202,7 +197,7 @@ namespace cppast
// note: does not consume the token if it is not valid, // note: does not consume the token if it is not valid,
// returns false in that case // returns false in that case
bool append_scope(cxtoken_stream& stream, std::string& scope); bool append_scope(cxtoken_stream& stream, std::string& scope);
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_CXTOKENIZER_HPP_INCLUDED #endif // CPPAST_CXTOKENIZER_HPP_INCLUDED

View file

@ -28,7 +28,7 @@ detail::cxstring detail::get_type_kind_spelling(const CXType& type) noexcept
namespace namespace
{ {
std::mutex mtx; std::mutex mtx;
} }
void detail::print_cursor_info(const CXCursor& cur) noexcept void detail::print_cursor_info(const CXCursor& cur) noexcept

View file

@ -11,8 +11,8 @@
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
cxstring get_display_name(const CXCursor& cur) noexcept; cxstring get_display_name(const CXCursor& cur) noexcept;
cxstring get_cursor_kind_spelling(const CXCursor& cur) noexcept; cxstring get_cursor_kind_spelling(const CXCursor& cur) noexcept;
@ -25,7 +25,7 @@ namespace cppast
void print_tokens(const CXTranslationUnit& tu, const CXFile& file, void print_tokens(const CXTranslationUnit& tu, const CXFile& file,
const CXCursor& cur) noexcept; const CXCursor& cur) noexcept;
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_DEBUG_HELPER_HPP_INCLUDED #endif // CPPAST_DEBUG_HELPER_HPP_INCLUDED

View file

@ -4,16 +4,16 @@
#include <cppast/cpp_enum.hpp> #include <cppast/cpp_enum.hpp>
#include "parse_functions.hpp"
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"
#include "parse_functions.hpp"
using namespace cppast; using namespace cppast;
namespace namespace
{ {
std::unique_ptr<cpp_enum_value> parse_enum_value(const detail::parse_context& context, std::unique_ptr<cpp_enum_value> parse_enum_value(const detail::parse_context& context,
const CXCursor& cur) const CXCursor& cur)
{ {
if (clang_isAttribute(clang_getCursorKind(cur))) if (clang_isAttribute(clang_getCursorKind(cur)))
return nullptr; return nullptr;
@ -32,9 +32,8 @@ namespace
if (detail::skip_if(stream, "=")) if (detail::skip_if(stream, "="))
{ {
detail::visit_children(cur, [&](const CXCursor& child) { detail::visit_children(cur, [&](const CXCursor& child) {
DEBUG_ASSERT(clang_isExpression(child.kind) && !value, DEBUG_ASSERT(clang_isExpression(child.kind) && !value, detail::parse_error_handler{},
detail::parse_error_handler{}, cur, cur, "unexpected child cursor of enum value");
"unexpected child cursor of enum value");
value = detail::parse_expression(context, child); value = detail::parse_expression(context, child);
}); });
@ -44,11 +43,11 @@ namespace
std::move(value)); std::move(value));
result->add_attribute(attributes); result->add_attribute(attributes);
return result; return result;
} }
cpp_enum::builder make_enum_builder(const detail::parse_context& context, const CXCursor& cur, cpp_enum::builder make_enum_builder(const detail::parse_context& context, const CXCursor& cur,
type_safe::optional<cpp_entity_ref>& semantic_parent) type_safe::optional<cpp_entity_ref>& semantic_parent)
{ {
auto name = detail::get_cursor_name(cur); auto name = detail::get_cursor_name(cur);
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
detail::cxtoken_stream stream(tokenizer, cur); detail::cxtoken_stream stream(tokenizer, cur);
@ -61,11 +60,9 @@ namespace
std::string scope; std::string scope;
while (!detail::skip_if(stream, name.c_str())) while (!detail::skip_if(stream, name.c_str()))
if (!detail::append_scope(stream, scope)) if (!detail::append_scope(stream, scope))
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected tokens in enum name");
"unexpected tokens in enum name");
if (!scope.empty()) if (!scope.empty())
semantic_parent = semantic_parent = cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
std::move(scope)); std::move(scope));
// parse type // parse type
@ -75,8 +72,8 @@ namespace
auto result = cpp_enum::builder(name.c_str(), scoped, std::move(type), type_given); auto result = cpp_enum::builder(name.c_str(), scoped, std::move(type), type_given);
result.get().add_attribute(attributes); result.get().add_attribute(attributes);
return result; return result;
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_enum(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_enum(const detail::parse_context& context,
const CXCursor& cur) const CXCursor& cur)

View file

@ -4,11 +4,11 @@
#include <cppast/cpp_friend.hpp> #include <cppast/cpp_friend.hpp>
#include <cppast/cpp_template_parameter.hpp>
#include <cppast/cpp_template.hpp> #include <cppast/cpp_template.hpp>
#include <cppast/cpp_template_parameter.hpp>
#include "parse_functions.hpp"
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"
#include "parse_functions.hpp"
using namespace cppast; using namespace cppast;
@ -45,8 +45,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_friend(const detail::parse_context
// we can't use the other branch here, // we can't use the other branch here,
// as then the class name would be wrong // as then the class name would be wrong
auto name = detail::get_cursor_name(referenced); auto name = detail::get_cursor_name(referenced);
type = type = cpp_user_defined_type::build(
cpp_user_defined_type::build(cpp_type_ref(detail::get_entity_id(referenced), cpp_type_ref(detail::get_entity_id(referenced),
namespace_str + "::" + name.c_str())); namespace_str + "::" + name.c_str()));
} }
else else

View file

@ -12,9 +12,9 @@ using namespace cppast;
namespace namespace
{ {
std::unique_ptr<cpp_function_parameter> parse_parameter(const detail::parse_context& context, std::unique_ptr<cpp_function_parameter> parse_parameter(const detail::parse_context& context,
const CXCursor& cur) const CXCursor& cur)
{ {
auto name = detail::get_cursor_name(cur); auto name = detail::get_cursor_name(cur);
auto type = detail::parse_type(context, cur, clang_getCursorType(cur)); auto type = detail::parse_type(context, cur, clang_getCursorType(cur));
@ -25,16 +25,16 @@ namespace
if (name.empty()) if (name.empty())
result = cpp_function_parameter::build(std::move(type), std::move(default_value)); result = cpp_function_parameter::build(std::move(type), std::move(default_value));
else else
result = cpp_function_parameter::build(*context.idx, detail::get_entity_id(cur), result
name.c_str(), std::move(type), = cpp_function_parameter::build(*context.idx, detail::get_entity_id(cur), name.c_str(),
std::move(default_value)); std::move(type), std::move(default_value));
result->add_attribute(attributes); result->add_attribute(attributes);
return result; return result;
} }
template <class Builder> template <class Builder>
void add_parameters(const detail::parse_context& context, Builder& builder, const CXCursor& cur) void add_parameters(const detail::parse_context& context, Builder& builder, const CXCursor& cur)
{ {
if (clang_getCursorKind(cur) == CXCursor_FunctionTemplate) if (clang_getCursorKind(cur) == CXCursor_FunctionTemplate)
{ {
// clang_Cursor_getNumArguments() doesn't work here // clang_Cursor_getNumArguments() doesn't work here
@ -71,8 +71,8 @@ namespace
for (auto i = 0; i != no; ++i) for (auto i = 0; i != no; ++i)
try try
{ {
auto parameter = auto parameter
parse_parameter(context, clang_Cursor_getArgument(cur, unsigned(i))); = parse_parameter(context, clang_Cursor_getArgument(cur, unsigned(i)));
builder.add_parameter(std::move(parameter)); builder.add_parameter(std::move(parameter));
} }
catch (detail::parse_error& ex) catch (detail::parse_error& ex)
@ -88,50 +88,48 @@ namespace
diagnostic{ex.what(), diagnostic{ex.what(),
detail::make_location(context.file, detail::make_location(context.file,
clang_Cursor_getArgument(cur, clang_Cursor_getArgument(cur,
unsigned( unsigned(i))),
i))),
severity::error}); severity::error});
} }
} }
} }
bool is_templated_cursor(const CXCursor& cur) bool is_templated_cursor(const CXCursor& cur)
{ {
return clang_getTemplateCursorKind(cur) != CXCursor_NoDeclFound return clang_getTemplateCursorKind(cur) != CXCursor_NoDeclFound
|| !clang_Cursor_isNull(clang_getSpecializedCursorTemplate(cur)); || !clang_Cursor_isNull(clang_getSpecializedCursorTemplate(cur));
} }
// precondition: after the name // precondition: after the name
void skip_parameters(detail::cxtoken_stream& stream) void skip_parameters(detail::cxtoken_stream& stream)
{ {
if (stream.peek() == "<") if (stream.peek() == "<")
// specialization arguments // specialization arguments
detail::skip_brackets(stream); detail::skip_brackets(stream);
detail::skip_brackets(stream); detail::skip_brackets(stream);
} }
std::vector<CXCursor> get_semantic_parents(CXCursor cur) std::vector<CXCursor> get_semantic_parents(CXCursor cur)
{ {
std::vector<CXCursor> result; std::vector<CXCursor> result;
for (; !clang_isTranslationUnit(clang_getCursorKind(cur)); for (; !clang_isTranslationUnit(clang_getCursorKind(cur));
cur = clang_getCursorSemanticParent(cur)) cur = clang_getCursorSemanticParent(cur))
result.push_back(cur); result.push_back(cur);
return result; return result;
} }
bool is_class(const CXCursor& parent) bool is_class(const CXCursor& parent)
{ {
auto kind = clang_getCursorKind(parent); auto kind = clang_getCursorKind(parent);
return kind == CXCursor_ClassDecl || kind == CXCursor_StructDecl return kind == CXCursor_ClassDecl || kind == CXCursor_StructDecl || kind == CXCursor_UnionDecl
|| kind == CXCursor_UnionDecl || kind == CXCursor_ClassTemplate || kind == CXCursor_ClassTemplate || kind == CXCursor_ClassTemplatePartialSpecialization;
|| kind == CXCursor_ClassTemplatePartialSpecialization; }
}
// returns the scope where the function is contained in // returns the scope where the function is contained in
// for regular functions that is the lexcial parent // for regular functions that is the lexcial parent
// for friend functions it is the enclosing scope of the class // for friend functions it is the enclosing scope of the class
CXCursor get_definition_scope(const CXCursor& cur, bool is_friend) CXCursor get_definition_scope(const CXCursor& cur, bool is_friend)
{ {
auto parent = clang_getCursorLexicalParent(cur); auto parent = clang_getCursorLexicalParent(cur);
if (is_friend) if (is_friend)
{ {
@ -146,20 +144,19 @@ namespace
"unable to find definition scope of friend"); "unable to find definition scope of friend");
} }
return parent; return parent;
} }
bool equivalent_cursor(const CXCursor& a, const CXCursor& b) bool equivalent_cursor(const CXCursor& a, const CXCursor& b)
{ {
if (clang_getCursorKind(a) == clang_getCursorKind(b) if (clang_getCursorKind(a) == clang_getCursorKind(b)
&& clang_getCursorKind(a) == CXCursor_Namespace) && clang_getCursorKind(a) == CXCursor_Namespace)
return detail::cxstring(clang_getCursorUSR(a)) return detail::cxstring(clang_getCursorUSR(a)) == detail::cxstring(clang_getCursorUSR(b));
== detail::cxstring(clang_getCursorUSR(b));
else else
return clang_equalCursors(a, b) == 1; return clang_equalCursors(a, b) == 1;
} }
type_safe::optional<cpp_entity_ref> parse_scope(const CXCursor& cur, bool is_friend) type_safe::optional<cpp_entity_ref> parse_scope(const CXCursor& cur, bool is_friend)
{ {
std::string scope_name; std::string scope_name;
auto friended = clang_getCursorReferenced(cur); auto friended = clang_getCursorReferenced(cur);
@ -201,8 +198,7 @@ namespace
// and the scope outside of the class for friend functions // and the scope outside of the class for friend functions
for (auto definition = get_definition_scope(cur, is_friend), for (auto definition = get_definition_scope(cur, is_friend),
parent = clang_getCursorSemanticParent(cur); parent = clang_getCursorSemanticParent(cur);
!equivalent_cursor(definition, parent); !equivalent_cursor(definition, parent); parent = clang_getCursorSemanticParent(parent))
parent = clang_getCursorSemanticParent(parent))
{ {
DEBUG_ASSERT(!clang_isTranslationUnit(clang_getCursorKind(parent)), DEBUG_ASSERT(!clang_isTranslationUnit(clang_getCursorKind(parent)),
detail::parse_error_handler{}, cur, detail::parse_error_handler{}, cur,
@ -217,20 +213,20 @@ namespace
else else
return cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)), return cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
std::move(scope_name)); std::move(scope_name));
} }
// just the tokens occurring in the prefix // just the tokens occurring in the prefix
struct prefix_info struct prefix_info
{ {
cpp_attribute_list attributes; cpp_attribute_list attributes;
bool is_constexpr = false; bool is_constexpr = false;
bool is_virtual = false; bool is_virtual = false;
bool is_explicit = false; bool is_explicit = false;
bool is_friend = false; bool is_friend = false;
}; };
bool prefix_end(detail::cxtoken_stream& stream, const char* name, bool is_ctor_dtor) bool prefix_end(detail::cxtoken_stream& stream, const char* name, bool is_ctor_dtor)
{ {
auto cur = stream.cur(); auto cur = stream.cur();
// name can have multiple tokens if it is an operator // name can have multiple tokens if it is an operator
if (!detail::skip_if(stream, name, true)) if (!detail::skip_if(stream, name, true))
@ -280,11 +276,10 @@ namespace
} }
else else
return true; return true;
} }
prefix_info parse_prefix_info(detail::cxtoken_stream& stream, const char* name, prefix_info parse_prefix_info(detail::cxtoken_stream& stream, const char* name, bool is_ctor_dtor)
bool is_ctor_dtor) {
{
prefix_info result; prefix_info result;
while (!stream.done() && !prefix_end(stream, name, is_ctor_dtor)) while (!stream.done() && !prefix_end(stream, name, is_ctor_dtor))
@ -298,8 +293,7 @@ namespace
else else
{ {
auto attributes = detail::parse_attributes(stream, true); auto attributes = detail::parse_attributes(stream, true);
result.attributes.insert(result.attributes.end(), attributes.begin(), result.attributes.insert(result.attributes.end(), attributes.begin(), attributes.end());
attributes.end());
} }
} }
DEBUG_ASSERT(!stream.done(), detail::parse_error_handler{}, stream.cursor(), DEBUG_ASSERT(!stream.done(), detail::parse_error_handler{}, stream.cursor(),
@ -312,11 +306,11 @@ namespace
result.attributes.insert(result.attributes.end(), attributes.begin(), attributes.end()); result.attributes.insert(result.attributes.end(), attributes.begin(), attributes.end());
return result; return result;
} }
// just the tokens occurring in the suffix // just the tokens occurring in the suffix
struct suffix_info struct suffix_info
{ {
cpp_attribute_list attributes; cpp_attribute_list attributes;
std::unique_ptr<cpp_expression> noexcept_condition; std::unique_ptr<cpp_expression> noexcept_condition;
cpp_function_body_kind body_kind; cpp_function_body_kind body_kind;
@ -325,14 +319,12 @@ namespace
cpp_virtual virtual_keywords; cpp_virtual virtual_keywords;
suffix_info(const CXCursor& cur) suffix_info(const CXCursor& cur)
: body_kind(clang_isCursorDefinition(cur) ? cpp_function_definition : : body_kind(clang_isCursorDefinition(cur) ? cpp_function_definition : cpp_function_declaration)
cpp_function_declaration) {}
{ };
}
};
cpp_cv parse_cv(detail::cxtoken_stream& stream) cpp_cv parse_cv(detail::cxtoken_stream& stream)
{ {
if (detail::skip_if(stream, "const")) if (detail::skip_if(stream, "const"))
{ {
if (detail::skip_if(stream, "volatile")) if (detail::skip_if(stream, "volatile"))
@ -349,21 +341,21 @@ namespace
} }
else else
return cpp_cv_none; return cpp_cv_none;
} }
cpp_reference parse_ref(detail::cxtoken_stream& stream) cpp_reference parse_ref(detail::cxtoken_stream& stream)
{ {
if (detail::skip_if(stream, "&")) if (detail::skip_if(stream, "&"))
return cpp_ref_lvalue; return cpp_ref_lvalue;
else if (detail::skip_if(stream, "&&")) else if (detail::skip_if(stream, "&&"))
return cpp_ref_rvalue; return cpp_ref_rvalue;
else else
return cpp_ref_none; return cpp_ref_none;
} }
std::unique_ptr<cpp_expression> parse_noexcept(detail::cxtoken_stream& stream, std::unique_ptr<cpp_expression> parse_noexcept(detail::cxtoken_stream& stream,
const detail::parse_context& context) const detail::parse_context& context)
{ {
if (!detail::skip_if(stream, "noexcept")) if (!detail::skip_if(stream, "noexcept"))
return nullptr; return nullptr;
@ -378,10 +370,10 @@ namespace
detail::skip(stream, ")"); detail::skip(stream, ")");
return expr; return expr;
} }
cpp_function_body_kind parse_body_kind(detail::cxtoken_stream& stream, bool& pure_virtual) cpp_function_body_kind parse_body_kind(detail::cxtoken_stream& stream, bool& pure_virtual)
{ {
pure_virtual = false; pure_virtual = false;
if (detail::skip_if(stream, "default")) if (detail::skip_if(stream, "default"))
return cpp_function_defaulted; return cpp_function_defaulted;
@ -396,10 +388,10 @@ namespace
DEBUG_UNREACHABLE(detail::parse_error_handler{}, stream.cursor(), DEBUG_UNREACHABLE(detail::parse_error_handler{}, stream.cursor(),
"unexpected token for function body kind"); "unexpected token for function body kind");
return cpp_function_declaration; return cpp_function_declaration;
} }
void parse_body(detail::cxtoken_stream& stream, suffix_info& result, bool allow_virtual) void parse_body(detail::cxtoken_stream& stream, suffix_info& result, bool allow_virtual)
{ {
auto pure_virtual = false; auto pure_virtual = false;
result.body_kind = parse_body_kind(stream, pure_virtual); result.body_kind = parse_body_kind(stream, pure_virtual);
if (pure_virtual) if (pure_virtual)
@ -411,13 +403,12 @@ namespace
else else
result.virtual_keywords = cpp_virtual_flags::pure; result.virtual_keywords = cpp_virtual_flags::pure;
} }
} }
// precondition: we've skipped the function parameters // precondition: we've skipped the function parameters
suffix_info parse_suffix_info(detail::cxtoken_stream& stream, suffix_info parse_suffix_info(detail::cxtoken_stream& stream, const detail::parse_context& context,
const detail::parse_context& context, bool allow_qualifier, bool allow_qualifier, bool allow_virtual)
bool allow_virtual) {
{
suffix_info result(stream.cursor()); suffix_info result(stream.cursor());
// syntax: <attribute> <cv> <ref> <exception> // syntax: <attribute> <cv> <ref> <exception>
@ -507,8 +498,7 @@ namespace
auto attributes = detail::parse_attributes(stream); auto attributes = detail::parse_attributes(stream);
if (!attributes.empty()) if (!attributes.empty())
result.attributes.insert(result.attributes.end(), attributes.begin(), result.attributes.insert(result.attributes.end(), attributes.begin(), attributes.end());
attributes.end());
if (detail::skip_if(stream, "=")) if (detail::skip_if(stream, "="))
parse_body(stream, result, allow_virtual); parse_body(stream, result, allow_virtual);
@ -518,12 +508,12 @@ namespace
} }
return result; return result;
} }
std::unique_ptr<cpp_entity> parse_cpp_function_impl(const detail::parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_function_impl(const detail::parse_context& context,
const CXCursor& cur, bool is_static, const CXCursor& cur, bool is_static,
bool is_friend) bool is_friend)
{ {
auto name = detail::get_cursor_name(cur); auto name = detail::get_cursor_name(cur);
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
@ -534,8 +524,7 @@ namespace
"free function cannot be virtual or explicit"); "free function cannot be virtual or explicit");
cpp_function::builder builder(name.c_str(), cpp_function::builder builder(name.c_str(),
detail::parse_type(context, cur, detail::parse_type(context, cur, clang_getCursorResultType(cur)));
clang_getCursorResultType(cur)));
context.comments.match(builder.get(), cur); context.comments.match(builder.get(), cur);
builder.get().add_attribute(prefix.attributes); builder.get().add_attribute(prefix.attributes);
@ -561,8 +550,8 @@ namespace
else else
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind, return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind,
parse_scope(cur, is_friend)); parse_scope(cur, is_friend));
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_function(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_function(const detail::parse_context& context,
const CXCursor& cur, bool is_friend) const CXCursor& cur, bool is_friend)
@ -587,25 +576,24 @@ std::unique_ptr<cpp_entity> detail::try_parse_static_cpp_function(
namespace namespace
{ {
bool overrides_function(const CXCursor& cur) bool overrides_function(const CXCursor& cur)
{ {
CXCursor* overrides = nullptr; CXCursor* overrides = nullptr;
auto num = 0u; auto num = 0u;
clang_getOverriddenCursors(cur, &overrides, &num); clang_getOverriddenCursors(cur, &overrides, &num);
clang_disposeOverriddenCursors(overrides); clang_disposeOverriddenCursors(overrides);
return num != 0u; return num != 0u;
} }
cpp_virtual calculate_virtual(const CXCursor& cur, bool virtual_keyword, cpp_virtual calculate_virtual(const CXCursor& cur, bool virtual_keyword,
const cpp_virtual& virtual_suffix) const cpp_virtual& virtual_suffix)
{ {
if (!clang_CXXMethod_isVirtual(cur) && !virtual_keyword && !virtual_suffix) if (!clang_CXXMethod_isVirtual(cur) && !virtual_keyword && !virtual_suffix)
return {}; return {};
else if (clang_CXXMethod_isPureVirtual(cur)) else if (clang_CXXMethod_isPureVirtual(cur))
{ {
// pure virtual function - all information in the suffix // pure virtual function - all information in the suffix
DEBUG_ASSERT(virtual_suffix.has_value() DEBUG_ASSERT(virtual_suffix.has_value() && virtual_suffix.value() & cpp_virtual_flags::pure,
&& virtual_suffix.value() & cpp_virtual_flags::pure,
detail::parse_error_handler{}, cur, "pure virtual not detected"); detail::parse_error_handler{}, cur, "pure virtual not detected");
return virtual_suffix; return virtual_suffix;
} }
@ -632,28 +620,28 @@ namespace
result.value() |= cpp_virtual_flags::override; result.value() |= cpp_virtual_flags::override;
return result; return result;
} }
} }
template <class Builder> template <class Builder>
auto set_qualifier(int, Builder& b, cpp_cv cv, cpp_reference ref) auto set_qualifier(int, Builder& b, cpp_cv cv, cpp_reference ref)
-> decltype(b.cv_ref_qualifier(cv, ref), true) -> decltype(b.cv_ref_qualifier(cv, ref), true)
{ {
b.cv_ref_qualifier(cv, ref); b.cv_ref_qualifier(cv, ref);
return true; return true;
} }
template <class Builder> template <class Builder>
bool set_qualifier(short, Builder&, cpp_cv, cpp_reference) bool set_qualifier(short, Builder&, cpp_cv, cpp_reference)
{ {
return false; return false;
} }
template <class Builder> template <class Builder>
std::unique_ptr<cpp_entity> handle_suffix(const detail::parse_context& context, std::unique_ptr<cpp_entity> handle_suffix(const detail::parse_context& context, const CXCursor& cur,
const CXCursor& cur, Builder& builder, Builder& builder, detail::cxtoken_stream& stream,
detail::cxtoken_stream& stream, bool is_virtual, bool is_virtual,
type_safe::optional<cpp_entity_ref> semantic_parent) type_safe::optional<cpp_entity_ref> semantic_parent)
{ {
auto allow_qualifiers = set_qualifier(0, builder, cpp_cv_none, cpp_ref_none); auto allow_qualifiers = set_qualifier(0, builder, cpp_cv_none, cpp_ref_none);
auto suffix = parse_suffix_info(stream, context, allow_qualifiers, true); auto suffix = parse_suffix_info(stream, context, allow_qualifiers, true);
@ -670,8 +658,8 @@ namespace
else else
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind, return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind,
std::move(semantic_parent)); std::move(semantic_parent));
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::parse_context& context,
const CXCursor& cur, bool is_friend) const CXCursor& cur, bool is_friend)

View file

@ -4,8 +4,8 @@
#include "parse_functions.hpp" #include "parse_functions.hpp"
#include <cppast/cpp_language_linkage.hpp>
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <cppast/cpp_language_linkage.hpp>
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"

View file

@ -10,12 +10,12 @@
#include <clang-c/CXCompilationDatabase.h> #include <clang-c/CXCompilationDatabase.h>
#include "cxtokenizer.hpp"
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"
#include "raii_wrapper.hpp"
#include "parse_error.hpp" #include "parse_error.hpp"
#include "parse_functions.hpp" #include "parse_functions.hpp"
#include "preprocessor.hpp" #include "preprocessor.hpp"
#include "cxtokenizer.hpp" #include "raii_wrapper.hpp"
using namespace cppast; using namespace cppast;
@ -81,8 +81,8 @@ bool libclang_compilation_database::has_config(const char* file_name) const
namespace namespace
{ {
int parse_number(const char*& str) int parse_number(const char*& str)
{ {
auto result = 0; auto result = 0;
for (; *str && *str != '.'; ++str) for (; *str && *str != '.'; ++str)
{ {
@ -90,13 +90,11 @@ namespace
result += int(*str - '0'); result += int(*str - '0');
} }
return result; return result;
} }
} // namespace } // namespace
libclang_compile_config::libclang_compile_config() libclang_compile_config::libclang_compile_config()
: compile_config({}), : compile_config({}), write_preprocessed_(false), fast_preprocessing_(false),
write_preprocessed_(false),
fast_preprocessing_(false),
remove_comments_in_macro_(false) remove_comments_in_macro_(false)
{ {
// set given clang binary // set given clang binary
@ -117,29 +115,28 @@ libclang_compile_config::libclang_compile_config()
namespace namespace
{ {
struct cxcompile_commands_deleter struct cxcompile_commands_deleter
{ {
void operator()(CXCompileCommands cmds) void operator()(CXCompileCommands cmds)
{ {
clang_CompileCommands_dispose(cmds); clang_CompileCommands_dispose(cmds);
} }
}; };
using cxcompile_commands = detail::raii_wrapper<CXCompileCommands, cxcompile_commands_deleter>; using cxcompile_commands = detail::raii_wrapper<CXCompileCommands, cxcompile_commands_deleter>;
bool has_drive_prefix(const std::string& file) bool has_drive_prefix(const std::string& file)
{ {
return file.size() > 2 && file[1] == ':'; return file.size() > 2 && file[1] == ':';
} }
bool is_absolute(const std::string& file) bool is_absolute(const std::string& file)
{ {
return !file.empty() return !file.empty() && (has_drive_prefix(file) || file.front() == '/' || file.front() == '\\');
&& (has_drive_prefix(file) || file.front() == '/' || file.front() == '\\'); }
}
std::string get_full_path(const detail::cxstring& dir, const std::string& file) std::string get_full_path(const detail::cxstring& dir, const std::string& file)
{ {
if (is_absolute(file)) if (is_absolute(file))
// absolute file // absolute file
return file; return file;
@ -149,7 +146,7 @@ namespace
else else
// relative w/o separator // relative w/o separator
return dir.std_str() + file; return dir.std_str() + file;
} }
} // namespace } // namespace
void detail::for_each_file(const libclang_compilation_database& database, void* user_data, void detail::for_each_file(const libclang_compilation_database& database, void* user_data,
@ -170,22 +167,22 @@ void detail::for_each_file(const libclang_compilation_database& database, void*
namespace namespace
{ {
bool is_flag(const detail::cxstring& str) bool is_flag(const detail::cxstring& str)
{ {
return str.length() > 1u && str[0] == '-'; return str.length() > 1u && str[0] == '-';
} }
const char* find_flag_arg_sep(const std::string& last_flag) const char* find_flag_arg_sep(const std::string& last_flag)
{ {
if (last_flag[1] == 'D') if (last_flag[1] == 'D')
// no separator, equal is part of the arg // no separator, equal is part of the arg
return nullptr; return nullptr;
return std::strchr(last_flag.c_str(), '='); return std::strchr(last_flag.c_str(), '=');
} }
template <typename Func> template <typename Func>
void parse_flags(CXCompileCommand cmd, Func callback) void parse_flags(CXCompileCommand cmd, Func callback)
{ {
auto no_args = clang_CompileCommand_getNumArgs(cmd); auto no_args = clang_CompileCommand_getNumArgs(cmd);
std::string last_flag; std::string last_flag;
for (auto i = 1u /* 0 is compiler executable */; i != no_args; ++i) for (auto i = 1u /* 0 is compiler executable */; i != no_args; ++i)
@ -225,15 +222,15 @@ namespace
} }
// else skip argument // else skip argument
} }
} }
} // namespace } // namespace
libclang_compile_config::libclang_compile_config(const libclang_compilation_database& database, libclang_compile_config::libclang_compile_config(const libclang_compilation_database& database,
const std::string& file) const std::string& file)
: libclang_compile_config() : libclang_compile_config()
{ {
auto cxcommands = auto cxcommands
clang_CompilationDatabase_getCompileCommands(database.database_, file.c_str()); = clang_CompilationDatabase_getCompileCommands(database.database_, file.c_str());
if (cxcommands == nullptr) if (cxcommands == nullptr)
throw libclang_error(detail::format("no compile commands specified for file '", file, "'")); throw libclang_error(detail::format("no compile commands specified for file '", file, "'"));
cxcompile_commands commands(cxcommands); cxcompile_commands commands(cxcommands);
@ -353,8 +350,8 @@ type_safe::optional<libclang_compile_config> cppast::find_config_for(
if (database.has_config(file_name)) if (database.has_config(file_name))
return libclang_compile_config(database, std::move(file_name)); return libclang_compile_config(database, std::move(file_name));
static const char* extensions[] = {".h", ".hpp", ".cpp", ".h++", ".c++", ".hxx", static const char* extensions[]
".cxx", ".hh", ".cc", ".H", ".C"}; = {".h", ".hpp", ".cpp", ".h++", ".c++", ".hxx", ".cxx", ".hh", ".cc", ".H", ".C"};
for (auto ext : extensions) for (auto ext : extensions)
{ {
auto name = file_name + ext; auto name = file_name + ext;
@ -370,32 +367,30 @@ struct libclang_parser::impl
detail::cxindex index; detail::cxindex index;
impl() : index(clang_createIndex(0, 0)) // no diagnostic, other one is irrelevant impl() : index(clang_createIndex(0, 0)) // no diagnostic, other one is irrelevant
{ {}
}
}; };
libclang_parser::libclang_parser() : libclang_parser(default_logger()) {} libclang_parser::libclang_parser() : libclang_parser(default_logger()) {}
libclang_parser::libclang_parser(type_safe::object_ref<const diagnostic_logger> logger) libclang_parser::libclang_parser(type_safe::object_ref<const diagnostic_logger> logger)
: parser(logger), pimpl_(new impl) : parser(logger), pimpl_(new impl)
{ {}
}
libclang_parser::~libclang_parser() noexcept {} libclang_parser::~libclang_parser() noexcept {}
namespace namespace
{ {
std::vector<const char*> get_arguments(const libclang_compile_config& config) std::vector<const char*> get_arguments(const libclang_compile_config& config)
{ {
std::vector<const char*> args = std::vector<const char*> args
{"-x", "c++", "-I."}; // force C++ and enable current directory for include search = {"-x", "c++", "-I."}; // force C++ and enable current directory for include search
for (auto& flag : detail::libclang_compile_config_access::flags(config)) for (auto& flag : detail::libclang_compile_config_access::flags(config))
args.push_back(flag.c_str()); args.push_back(flag.c_str());
return args; return args;
} }
type_safe::optional<severity> get_severity(const CXDiagnostic& diag) type_safe::optional<severity> get_severity(const CXDiagnostic& diag)
{ {
switch (clang_getDiagnosticSeverity(diag)) switch (clang_getDiagnosticSeverity(diag))
{ {
case CXDiagnostic_Ignored: case CXDiagnostic_Ignored:
@ -412,10 +407,10 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return type_safe::nullopt; return type_safe::nullopt;
} }
void print_diagnostics(const diagnostic_logger& logger, const CXTranslationUnit& tu) void print_diagnostics(const diagnostic_logger& logger, const CXTranslationUnit& tu)
{ {
auto no = clang_getNumDiagnostics(tu); auto no = clang_getNumDiagnostics(tu);
for (auto i = 0u; i != no; ++i) for (auto i = 0u; i != no; ++i)
{ {
@ -434,13 +429,12 @@ namespace
logger.log("libclang", diagnostic{text.c_str(), loc, sev.value()}); logger.log("libclang", diagnostic{text.c_str(), loc, sev.value()});
} }
} }
} }
detail::cxtranslation_unit get_cxunit(const diagnostic_logger& logger, detail::cxtranslation_unit get_cxunit(const diagnostic_logger& logger, const detail::cxindex& idx,
const detail::cxindex& idx,
const libclang_compile_config& config, const char* path, const libclang_compile_config& config, const char* path,
const std::string& source) const std::string& source)
{ {
CXUnsavedFile file; CXUnsavedFile file;
file.Filename = path; file.Filename = path;
file.Contents = source.c_str(); file.Contents = source.c_str();
@ -452,8 +446,8 @@ namespace
auto flags = CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing auto flags = CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing
| CXTranslationUnit_DetailedPreprocessingRecord; | CXTranslationUnit_DetailedPreprocessingRecord;
auto error = auto error
clang_parseTranslationUnit2(idx.get(), path, // index and path = clang_parseTranslationUnit2(idx.get(), path, // index and path
args.data(), args.data(),
static_cast<int>(args.size()), // arguments (ptr + size) static_cast<int>(args.size()), // arguments (ptr + size)
&file, 1, // unsaved files (ptr + size) &file, 1, // unsaved files (ptr + size)
@ -479,16 +473,16 @@ namespace
print_diagnostics(logger, tu); print_diagnostics(logger, tu);
return detail::cxtranslation_unit(tu); return detail::cxtranslation_unit(tu);
} }
unsigned get_line_no(const CXCursor& cursor) unsigned get_line_no(const CXCursor& cursor)
{ {
auto loc = clang_getCursorLocation(cursor); auto loc = clang_getCursorLocation(cursor);
unsigned line; unsigned line;
clang_getPresumedLocation(loc, nullptr, &line, nullptr); clang_getPresumedLocation(loc, nullptr, &line, nullptr);
return line; return line;
} }
} // namespace } // namespace
std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx, std::string path, std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx, std::string path,
@ -530,8 +524,8 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
&& get_line_no(cur) >= include_iter->line, && get_line_no(cur) >= include_iter->line,
detail::assert_handler{}); detail::assert_handler{});
auto full_path = include_iter->full_path.empty() ? include_iter->file_name : auto full_path = include_iter->full_path.empty() ? include_iter->file_name
include_iter->full_path; : include_iter->full_path;
// if we got an absolute file path for the current file, // if we got an absolute file path for the current file,
// also use an absolute file path for the id // also use an absolute file path for the id
@ -543,8 +537,8 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
else else
id = cpp_entity_id(include_iter->file_name.c_str()); id = cpp_entity_id(include_iter->file_name.c_str());
auto include = auto include
cpp_include_directive::build(cpp_file_ref(id, = cpp_include_directive::build(cpp_file_ref(id,
std::move(include_iter->file_name)), std::move(include_iter->file_name)),
include_iter->kind, std::move(full_path)); include_iter->kind, std::move(full_path));
context.comments.match(*include, include_iter->line, context.comments.match(*include, include_iter->line,

View file

@ -11,8 +11,8 @@
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
// visits direct children of an entity // visits direct children of an entity
template <typename Func> template <typename Func>
void visit_children(CXCursor parent, Func f, bool recurse = false) void visit_children(CXCursor parent, Func f, bool recurse = false)
@ -54,7 +54,7 @@ namespace cppast
f(cur); f(cur);
}); });
} }
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_LIBCLANG_VISITOR_HPP_INCLUDED #endif // CPPAST_LIBCLANG_VISITOR_HPP_INCLUDED

View file

@ -13,9 +13,8 @@ using namespace cppast;
namespace namespace
{ {
cpp_namespace::builder make_ns_builder(const detail::parse_context& context, cpp_namespace::builder make_ns_builder(const detail::parse_context& context, const CXCursor& cur)
const CXCursor& cur) {
{
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
detail::cxtoken_stream stream(tokenizer, cur); detail::cxtoken_stream stream(tokenizer, cur);
// [inline] namespace|:: [<attribute>] <identifier> [{] // [inline] namespace|:: [<attribute>] <identifier> [{]
@ -54,8 +53,8 @@ namespace
auto result = cpp_namespace::builder(name.c_str(), is_inline, is_nested); auto result = cpp_namespace::builder(name.c_str(), is_inline, is_nested);
result.get().add_attribute(attributes); result.get().add_attribute(attributes);
return result; return result;
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_namespace(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_namespace(const detail::parse_context& context,
cpp_entity& parent, const CXCursor& cur) cpp_entity& parent, const CXCursor& cur)
@ -83,8 +82,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_namespace(const detail::parse_cont
namespace namespace
{ {
cpp_entity_id parse_ns_target_cursor(const CXCursor& cur) cpp_entity_id parse_ns_target_cursor(const CXCursor& cur)
{ {
cpp_entity_id result(""); cpp_entity_id result("");
detail::visit_children(cur, detail::visit_children(cur,
[&](const CXCursor& child) { [&](const CXCursor& child) {
@ -102,8 +101,8 @@ namespace
}, },
true); true);
return result; return result;
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_namespace_alias(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_namespace_alias(const detail::parse_context& context,
const CXCursor& cur) const CXCursor& cur)
@ -155,8 +154,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_using_directive(const detail::pars
namespace namespace
{ {
cpp_entity_ref parse_entity_target_cursor(const CXCursor& cur, std::string name) cpp_entity_ref parse_entity_target_cursor(const CXCursor& cur, std::string name)
{ {
type_safe::deferred_construction<cpp_entity_ref> result; type_safe::deferred_construction<cpp_entity_ref> result;
detail::visit_children(cur, detail::visit_children(cur,
[&](const CXCursor& child) { [&](const CXCursor& child) {
@ -197,12 +196,11 @@ namespace
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur,
"unexpected target for using declaration"); "unexpected target for using declaration");
} }
}, },
true); true);
return result.value(); return result.value();
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_using_declaration( std::unique_ptr<cpp_entity> detail::parse_cpp_using_declaration(
const detail::parse_context& context, const CXCursor& cur) const detail::parse_context& context, const CXCursor& cur)

View file

@ -7,15 +7,15 @@
#include <stdexcept> #include <stdexcept>
#include <debug_assert.hpp>
#include <cppast/diagnostic.hpp> #include <cppast/diagnostic.hpp>
#include <debug_assert.hpp>
#include "debug_helper.hpp" #include "debug_helper.hpp"
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
inline source_location make_location(const CXCursor& cur) inline source_location make_location(const CXCursor& cur)
{ {
auto loc = clang_getCursorLocation(cur); auto loc = clang_getCursorLocation(cur);
@ -45,18 +45,15 @@ namespace cppast
public: public:
parse_error(source_location loc, std::string message) parse_error(source_location loc, std::string message)
: std::logic_error(std::move(message)), location_(std::move(loc)) : std::logic_error(std::move(message)), location_(std::move(loc))
{ {}
}
parse_error(const CXCursor& cur, std::string message) parse_error(const CXCursor& cur, std::string message)
: parse_error(make_location(cur), std::move(message)) : parse_error(make_location(cur), std::move(message))
{ {}
}
parse_error(const CXType& type, std::string message) parse_error(const CXType& type, std::string message)
: parse_error(make_location(type), std::move(message)) : parse_error(make_location(type), std::move(message))
{ {}
}
diagnostic get_diagnostic(const CXFile& file) diagnostic get_diagnostic(const CXFile& file)
{ {
@ -77,19 +74,19 @@ namespace cppast
// throws a parse_error exception // throws a parse_error exception
struct parse_error_handler : debug_assert::set_level<1>, debug_assert::allow_exception struct parse_error_handler : debug_assert::set_level<1>, debug_assert::allow_exception
{ {
static void handle(const debug_assert::source_location&, const char*, static void handle(const debug_assert::source_location&, const char*, const CXCursor& cur,
const CXCursor& cur, std::string message) std::string message)
{ {
throw parse_error(cur, std::move(message)); throw parse_error(cur, std::move(message));
} }
static void handle(const debug_assert::source_location&, const char*, static void handle(const debug_assert::source_location&, const char*, const CXType& type,
const CXType& type, std::string message) std::string message)
{ {
throw parse_error(type, std::move(message)); throw parse_error(type, std::move(message));
} }
}; };
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_PARSE_ERROR_HPP_INCLUDED #endif // CPPAST_PARSE_ERROR_HPP_INCLUDED

View file

@ -4,8 +4,8 @@
#include "parse_functions.hpp" #include "parse_functions.hpp"
#include <cppast/cpp_storage_class_specifiers.hpp>
#include <cppast/cpp_static_assert.hpp> #include <cppast/cpp_static_assert.hpp>
#include <cppast/cpp_storage_class_specifiers.hpp>
#include "libclang_visitor.hpp" #include "libclang_visitor.hpp"
@ -100,16 +100,16 @@ void detail::comment_context::match(cpp_entity& e, unsigned line, bool skip_comm
namespace namespace
{ {
bool is_friend(const CXCursor& parent_cur) bool is_friend(const CXCursor& parent_cur)
{ {
#if CPPAST_CINDEX_HAS_FRIEND #if CPPAST_CINDEX_HAS_FRIEND
return clang_getCursorKind(parent_cur) == CXCursor_FriendDecl; return clang_getCursorKind(parent_cur) == CXCursor_FriendDecl;
#else #else
(void)parent_cur; (void)parent_cur;
return false; return false;
#endif #endif
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& context,
cpp_entity* parent, const CXCursor& cur, cpp_entity* parent, const CXCursor& cur,
@ -165,25 +165,25 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
return parse_cpp_member_variable(context, cur); return parse_cpp_member_variable(context, cur);
case CXCursor_FunctionDecl: case CXCursor_FunctionDecl:
if (auto tfunc = if (auto tfunc
try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur))) = try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur)))
return tfunc; return tfunc;
return parse_cpp_function(context, cur, is_friend(parent_cur)); return parse_cpp_function(context, cur, is_friend(parent_cur));
case CXCursor_CXXMethod: case CXCursor_CXXMethod:
if (auto tfunc = if (auto tfunc
try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur))) = try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur)))
return tfunc; return tfunc;
else if (auto func = try_parse_static_cpp_function(context, cur)) else if (auto func = try_parse_static_cpp_function(context, cur))
return func; return func;
return parse_cpp_member_function(context, cur, is_friend(parent_cur)); return parse_cpp_member_function(context, cur, is_friend(parent_cur));
case CXCursor_ConversionFunction: case CXCursor_ConversionFunction:
if (auto tfunc = if (auto tfunc
try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur))) = try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur)))
return tfunc; return tfunc;
return parse_cpp_conversion_op(context, cur, is_friend(parent_cur)); return parse_cpp_conversion_op(context, cur, is_friend(parent_cur));
case CXCursor_Constructor: case CXCursor_Constructor:
if (auto tfunc = if (auto tfunc
try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur))) = try_parse_cpp_function_template_specialization(context, cur, is_friend(parent_cur)))
return tfunc; return tfunc;
return parse_cpp_constructor(context, cur, is_friend(parent_cur)); return parse_cpp_constructor(context, cur, is_friend(parent_cur));
case CXCursor_Destructor: case CXCursor_Destructor:

View file

@ -8,25 +8,25 @@
#include <cppast/cpp_entity.hpp> #include <cppast/cpp_entity.hpp>
#include <cppast/parser.hpp> #include <cppast/parser.hpp>
#include "raii_wrapper.hpp"
#include "cxtokenizer.hpp" // for convenience #include "cxtokenizer.hpp" // for convenience
#include "parse_error.hpp" // for convenience #include "parse_error.hpp" // for convenience
#include "preprocessor.hpp" #include "preprocessor.hpp"
#include "raii_wrapper.hpp"
#if CINDEX_VERSION_MINOR >= 36 #if CINDEX_VERSION_MINOR >= 36
#define CPPAST_CINDEX_HAS_FRIEND 1 # define CPPAST_CINDEX_HAS_FRIEND 1
#else #else
#define CPPAST_CINDEX_HAS_FRIEND 0 # define CPPAST_CINDEX_HAS_FRIEND 0
#endif #endif
namespace cppast namespace cppast
{ {
class cpp_expression; class cpp_expression;
class cpp_type; class cpp_type;
enum cpp_storage_class_specifiers : int; enum cpp_storage_class_specifiers : int;
namespace detail namespace detail
{ {
cpp_entity_id get_entity_id(const CXCursor& cur); cpp_entity_id get_entity_id(const CXCursor& cur);
// only use this if the name is just a single token // only use this if the name is just a single token
@ -42,8 +42,7 @@ namespace cppast
public: public:
explicit comment_context(std::vector<pp_doc_comment>& comments) explicit comment_context(std::vector<pp_doc_comment>& comments)
: cur_(comments.data()), end_(comments.data() + comments.size()) : cur_(comments.data()), end_(comments.data() + comments.size())
{ {}
}
// must be called for entities that want an associated comment // must be called for entities that want an associated comment
// must be called *BEFORE* the children are added // must be called *BEFORE* the children are added
@ -77,8 +76,8 @@ namespace cppast
// and ends at the given iterator // and ends at the given iterator
// this is required for situations where there is no type exposed, // this is required for situations where there is no type exposed,
// like default type of a template type parameter // like default type of a template type parameter
std::unique_ptr<cpp_type> parse_raw_type(const parse_context& context, std::unique_ptr<cpp_type> parse_raw_type(const parse_context& context, cxtoken_stream& stream,
cxtoken_stream& stream, cxtoken_iterator end); cxtoken_iterator end);
std::unique_ptr<cpp_expression> parse_expression(const parse_context& context, std::unique_ptr<cpp_expression> parse_expression(const parse_context& context,
const CXCursor& cur); const CXCursor& cur);
@ -123,10 +122,8 @@ namespace cppast
std::unique_ptr<cpp_entity> parse_cpp_type_alias(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_type_alias(const parse_context& context,
const CXCursor& cur, const CXCursor& cur,
const CXCursor& template_cur); const CXCursor& template_cur);
std::unique_ptr<cpp_entity> parse_cpp_enum(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_enum(const parse_context& context, const CXCursor& cur);
const CXCursor& cur); std::unique_ptr<cpp_entity> parse_cpp_class(const parse_context& context, const CXCursor& cur,
std::unique_ptr<cpp_entity> parse_cpp_class(const parse_context& context,
const CXCursor& cur,
const CXCursor& parent_cur); const CXCursor& parent_cur);
std::unique_ptr<cpp_entity> parse_cpp_variable(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_variable(const parse_context& context,
@ -146,14 +143,12 @@ namespace cppast
std::unique_ptr<cpp_entity> parse_cpp_destructor(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_destructor(const parse_context& context,
const CXCursor& cur, bool is_friend); const CXCursor& cur, bool is_friend);
std::unique_ptr<cpp_entity> parse_cpp_friend(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_friend(const parse_context& context, const CXCursor& cur);
const CXCursor& cur);
std::unique_ptr<cpp_entity> parse_cpp_alias_template(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_alias_template(const parse_context& context,
const CXCursor& cur); const CXCursor& cur);
std::unique_ptr<cpp_entity> parse_cpp_function_template(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_function_template(const parse_context& context,
const CXCursor& cur, const CXCursor& cur, bool is_friend);
bool is_friend);
std::unique_ptr<cpp_entity> parse_cpp_class_template(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_class_template(const parse_context& context,
const CXCursor& cur); const CXCursor& cur);
std::unique_ptr<cpp_entity> parse_cpp_class_template_specialization( std::unique_ptr<cpp_entity> parse_cpp_class_template_specialization(
@ -164,10 +159,10 @@ namespace cppast
// parent: used for nested namespace, doesn't matter otherwise // parent: used for nested namespace, doesn't matter otherwise
// parent_cur: used when parsing templates or friends // parent_cur: used when parsing templates or friends
std::unique_ptr<cpp_entity> parse_entity( std::unique_ptr<cpp_entity> parse_entity(const parse_context& context, cpp_entity* parent,
const parse_context& context, cpp_entity* parent, const CXCursor& cur, const CXCursor& cur,
const CXCursor& parent_cur = clang_getNullCursor()); const CXCursor& parent_cur = clang_getNullCursor());
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_PARSE_FUNCTIONS_HPP_INCLUDED #endif // CPPAST_PARSE_FUNCTIONS_HPP_INCLUDED

View file

@ -32,9 +32,9 @@ bool detail::pp_doc_comment::matches(const cpp_entity&, unsigned e_line)
namespace namespace
{ {
//=== diagnostic parsing ===// //=== diagnostic parsing ===//
source_location parse_source_location(const char*& ptr) source_location parse_source_location(const char*& ptr)
{ {
// format: <filename>(<line>): // format: <filename>(<line>):
// or: <filename>: // or: <filename>:
auto fallback = ptr; auto fallback = ptr;
@ -65,10 +65,10 @@ namespace
++ptr; ++ptr;
return {type_safe::nullopt, std::move(filename), std::move(line), type_safe::nullopt}; return {type_safe::nullopt, std::move(filename), std::move(line), type_safe::nullopt};
} }
severity parse_severity(const char*& ptr) severity parse_severity(const char*& ptr)
{ {
// format: <severity>: // format: <severity>:
auto fallback = ptr; auto fallback = ptr;
std::string sev; std::string sev;
@ -85,11 +85,11 @@ namespace
else else
ptr = fallback; ptr = fallback;
return severity::error; return severity::error;
} }
// parse and log diagnostic // parse and log diagnostic
void log_diagnostic(const diagnostic_logger& logger, const std::string& msg) void log_diagnostic(const diagnostic_logger& logger, const std::string& msg)
{ {
auto ptr = msg.c_str(); auto ptr = msg.c_str();
auto loc = parse_source_location(ptr); auto loc = parse_source_location(ptr);
@ -105,13 +105,12 @@ namespace
message.push_back(*ptr++); message.push_back(*ptr++);
logger.log("preprocessor", diagnostic{std::move(message), std::move(loc), sev}); logger.log("preprocessor", diagnostic{std::move(message), std::move(loc), sev});
} }
// parses missing header file diagnostic and returns the file name, // parses missing header file diagnostic and returns the file name,
// if it is a missing header file diagnostic // if it is a missing header file diagnostic
ts::optional<std::string> parse_missing_file(const std::string& cur_file, ts::optional<std::string> parse_missing_file(const std::string& cur_file, const std::string& msg)
const std::string& msg) {
{
auto ptr = msg.c_str(); auto ptr = msg.c_str();
auto loc = parse_source_location(ptr); auto loc = parse_source_location(ptr);
@ -139,17 +138,17 @@ namespace
return std::move(filename); return std::move(filename);
else else
throw libclang_error("preprocessor: unexpected diagnostic '" + msg + "'"); throw libclang_error("preprocessor: unexpected diagnostic '" + msg + "'");
} }
//=== external preprocessor invocation ==// //=== external preprocessor invocation ==//
// quote a string // quote a string
std::string quote(std::string str) std::string quote(std::string str)
{ {
return '"' + std::move(str) + '"'; return '"' + std::move(str) + '"';
} }
std::string diagnostics_flags() std::string diagnostics_flags()
{ {
std::string flags; std::string flags;
// -fno-caret-diagnostics: don't show the source extract in diagnostics // -fno-caret-diagnostics: don't show the source extract in diagnostics
@ -162,11 +161,11 @@ namespace
"-Wno-include-next-outside-header"; "-Wno-include-next-outside-header";
return flags; return flags;
} }
// get the command that returns all macros defined in the TU // get the command that returns all macros defined in the TU
std::string get_macro_command(const libclang_compile_config& c, const char* full_path) std::string get_macro_command(const libclang_compile_config& c, const char* full_path)
{ {
// -x c++: force C++ as input language // -x c++: force C++ as input language
// -I.: add current working directory to include search path // -I.: add current working directory to include search path
// -E: print preprocessor output // -E: print preprocessor output
@ -174,8 +173,8 @@ namespace
auto flags = std::string("-x c++ -I. -E -dM"); auto flags = std::string("-x c++ -I. -E -dM");
flags += diagnostics_flags(); flags += diagnostics_flags();
std::string cmd(detail::libclang_compile_config_access::clang_binary(c) + " " std::string cmd(detail::libclang_compile_config_access::clang_binary(c) + " " + std::move(flags)
+ std::move(flags) + " "); + " ");
// other flags // other flags
for (auto& flag : detail::libclang_compile_config_access::flags(c)) for (auto& flag : detail::libclang_compile_config_access::flags(c))
{ {
@ -184,13 +183,13 @@ namespace
} }
return cmd + quote(full_path); return cmd + quote(full_path);
} }
// get the command that preprocess a translation unit given the macros // get the command that preprocess a translation unit given the macros
// macro_file_path == nullptr <=> don't do fast preprocessing // macro_file_path == nullptr <=> don't do fast preprocessing
std::string get_preprocess_command(const libclang_compile_config& c, const char* full_path, std::string get_preprocess_command(const libclang_compile_config& c, const char* full_path,
const char* macro_file_path) const char* macro_file_path)
{ {
// -x c++: force C++ as input language // -x c++: force C++ as input language
// -E: print preprocessor output // -E: print preprocessor output
// -dD: keep macros // -dD: keep macros
@ -220,8 +219,8 @@ namespace
flags += macro_file_path; flags += macro_file_path;
} }
std::string cmd(detail::libclang_compile_config_access::clang_binary(c) + " " std::string cmd(detail::libclang_compile_config_access::clang_binary(c) + " " + std::move(flags)
+ std::move(flags) + " "); + " ");
// other flags // other flags
for (const auto& flag : detail::libclang_compile_config_access::flags(c)) for (const auto& flag : detail::libclang_compile_config_access::flags(c))
@ -237,17 +236,17 @@ namespace
} }
return cmd + quote(full_path); return cmd + quote(full_path);
} }
std::string get_macro_file_name() std::string get_macro_file_name()
{ {
static std::atomic<unsigned> counter(0u); static std::atomic<unsigned> counter(0u);
return "standardese-macro-file-" + std::to_string(++counter) + ".delete-me"; return "standardese-macro-file-" + std::to_string(++counter) + ".delete-me";
} }
template <std::size_t N> template <std::size_t N>
void bump_until(std::istreambuf_iterator<char>& iter, const char (&str)[N]) void bump_until(std::istreambuf_iterator<char>& iter, const char (&str)[N])
{ {
auto ptr = &str[0]; auto ptr = &str[0];
while (ptr != &str[N - 1]) while (ptr != &str[N - 1])
{ {
@ -267,27 +266,27 @@ namespace
++iter; ++iter;
} }
} }
template <typename Iter> template <typename Iter>
void skip_whitespace(Iter& begin, Iter end) void skip_whitespace(Iter& begin, Iter end)
{ {
while (begin != end && (*begin == ' ' || *begin == '\t')) while (begin != end && (*begin == ' ' || *begin == '\t'))
++begin; ++begin;
} }
template <typename Iter> template <typename Iter>
std::string get_line(Iter& begin, Iter end) std::string get_line(Iter& begin, Iter end)
{ {
std::string line; std::string line;
while (begin != end && *begin != '\n') while (begin != end && *begin != '\n')
line += *begin++; line += *begin++;
++begin; // newline ++begin; // newline
return line; return line;
} }
type_safe::optional<std::string> get_include_guard_macro(const std::string& full_path) type_safe::optional<std::string> get_include_guard_macro(const std::string& full_path)
{ {
std::ifstream file(full_path); std::ifstream file(full_path);
auto iter = std::istreambuf_iterator<char>(file); auto iter = std::istreambuf_iterator<char>(file);
@ -350,11 +349,11 @@ namespace
// assume no include guard followed a bad line // assume no include guard followed a bad line
return type_safe::nullopt; return type_safe::nullopt;
} }
std::string write_macro_file(const libclang_compile_config& c, const std::string& full_path, std::string write_macro_file(const libclang_compile_config& c, const std::string& full_path,
const diagnostic_logger& logger) const diagnostic_logger& logger)
{ {
std::string diagnostic; std::string diagnostic;
auto diagnostic_logger = [&](const char* str, std::size_t n) { auto diagnostic_logger = [&](const char* str, std::size_t n) {
diagnostic.reserve(diagnostic.size() + n); diagnostic.reserve(diagnostic.size() + n);
@ -392,19 +391,18 @@ namespace
+ "' exited with non-zero exit code (" + std::to_string(exit_code) + "' exited with non-zero exit code (" + std::to_string(exit_code)
+ ")"); + ")");
return file; return file;
} }
struct clang_preprocess_result struct clang_preprocess_result
{ {
std::string file; std::string file;
std::vector<std::string> included_files; // needed for pre-clang 4.0.0 std::vector<std::string> included_files; // needed for pre-clang 4.0.0
}; };
clang_preprocess_result clang_preprocess_impl(const libclang_compile_config& c, clang_preprocess_result clang_preprocess_impl(const libclang_compile_config& c,
const diagnostic_logger& logger, const diagnostic_logger& logger,
const std::string& full_path, const std::string& full_path, const char* macro_path)
const char* macro_path) {
{
clang_preprocess_result result; clang_preprocess_result result;
std::string diagnostic; std::string diagnostic;
@ -452,19 +450,17 @@ namespace
auto exit_code = process.get_exit_status(); auto exit_code = process.get_exit_status();
DEBUG_ASSERT(diagnostic.empty(), detail::assert_handler{}); DEBUG_ASSERT(diagnostic.empty(), detail::assert_handler{});
if (exit_code != 0 && !expect_bad_exit_code) if (exit_code != 0 && !expect_bad_exit_code)
throw libclang_error("preprocessor: command '" + cmd throw libclang_error("preprocessor: command '" + cmd + "' exited with non-zero exit code ("
+ "' exited with non-zero exit code (" + std::to_string(exit_code) + std::to_string(exit_code) + ")");
+ ")");
return result; return result;
} }
clang_preprocess_result clang_preprocess(const libclang_compile_config& c, clang_preprocess_result clang_preprocess(const libclang_compile_config& c, const char* full_path,
const char* full_path, const diagnostic_logger& logger) const diagnostic_logger& logger)
{ {
if (!std::ifstream(full_path)) if (!std::ifstream(full_path))
throw libclang_error("preprocessor: file '" + std::string(full_path) throw libclang_error("preprocessor: file '" + std::string(full_path) + "' doesn't exist");
+ "' doesn't exist");
// if we're fast preprocessing we only preprocess the main file, not includes // if we're fast preprocessing we only preprocess the main file, not includes
// this is done by disabling all include search paths when doing the preprocessing // this is done by disabling all include search paths when doing the preprocessing
@ -497,16 +493,15 @@ namespace
} }
return result; return result;
} }
//==== parsing ===// //==== parsing ===//
class position class position
{ {
public: public:
position(ts::object_ref<std::string> result, const char* ptr) noexcept position(ts::object_ref<std::string> result, const char* ptr) noexcept
: result_(result), cur_line_(1u), cur_column_(0u), ptr_(ptr), write_(true) : result_(result), cur_line_(1u), cur_column_(0u), ptr_(ptr), write_(true)
{ {}
}
void set_line(unsigned line) void set_line(unsigned line)
{ {
@ -624,41 +619,41 @@ namespace
return result_->empty() || result_->back() == '\n'; return result_->empty() || result_->back() == '\n';
} }
private: private:
ts::object_ref<std::string> result_; ts::object_ref<std::string> result_;
unsigned cur_line_, cur_column_; unsigned cur_line_, cur_column_;
const char* ptr_; const char* ptr_;
ts::flag write_; ts::flag write_;
}; };
bool starts_with(const position& p, const char* str, std::size_t len) bool starts_with(const position& p, const char* str, std::size_t len)
{ {
return std::strncmp(p.ptr(), str, len) == 0; return std::strncmp(p.ptr(), str, len) == 0;
} }
template <std::size_t N> template <std::size_t N>
bool starts_with(const position& p, const char (&str)[N]) bool starts_with(const position& p, const char (&str)[N])
{ {
return std::strncmp(p.ptr(), str, N - 1) == 0; return std::strncmp(p.ptr(), str, N - 1) == 0;
} }
void skip(position& p, const char* str) void skip(position& p, const char* str)
{ {
DEBUG_ASSERT(starts_with(p, str, std::strlen(str)), detail::assert_handler{}); DEBUG_ASSERT(starts_with(p, str, std::strlen(str)), detail::assert_handler{});
p.skip(std::strlen(str)); p.skip(std::strlen(str));
} }
void bump_spaces(position& p, bool bump = false) void bump_spaces(position& p, bool bump = false)
{ {
while (starts_with(p, " ")) while (starts_with(p, " "))
if (bump) if (bump)
p.bump(); p.bump();
else else
p.skip(); p.skip();
} }
detail::pp_doc_comment parse_c_doc_comment(position& p) detail::pp_doc_comment parse_c_doc_comment(position& p)
{ {
detail::pp_doc_comment result; detail::pp_doc_comment result;
result.kind = detail::pp_doc_comment::c; result.kind = detail::pp_doc_comment::c;
@ -734,10 +729,10 @@ namespace
result.line = p.cur_line(); result.line = p.cur_line();
return result; return result;
} }
bool skip_c_comment(position& p, detail::preprocessor_output& output) bool skip_c_comment(position& p, detail::preprocessor_output& output)
{ {
if (!starts_with(p, "/*")) if (!starts_with(p, "/*"))
return false; return false;
p.skip(2u); p.skip(2u);
@ -759,13 +754,12 @@ namespace
} }
return true; return true;
} }
detail::pp_doc_comment parse_cpp_doc_comment(position& p, bool end_of_line) detail::pp_doc_comment parse_cpp_doc_comment(position& p, bool end_of_line)
{ {
detail::pp_doc_comment result; detail::pp_doc_comment result;
result.kind = result.kind = end_of_line ? detail::pp_doc_comment::end_of_line : detail::pp_doc_comment::cpp;
end_of_line ? detail::pp_doc_comment::end_of_line : detail::pp_doc_comment::cpp;
if (starts_with(p, " ")) if (starts_with(p, " "))
// skip one whitespace at most // skip one whitespace at most
p.skip(); p.skip();
@ -782,17 +776,17 @@ namespace
result.comment.pop_back(); result.comment.pop_back();
result.line = p.cur_line(); result.line = p.cur_line();
return result; return result;
} }
bool can_merge_comment(const detail::pp_doc_comment& comment, unsigned cur_line) bool can_merge_comment(const detail::pp_doc_comment& comment, unsigned cur_line)
{ {
return comment.line + 1 == cur_line return comment.line + 1 == cur_line
&& (comment.kind == detail::pp_doc_comment::cpp && (comment.kind == detail::pp_doc_comment::cpp
|| comment.kind == detail::pp_doc_comment::end_of_line); || comment.kind == detail::pp_doc_comment::end_of_line);
} }
void merge_or_add(detail::preprocessor_output& output, detail::pp_doc_comment comment) void merge_or_add(detail::preprocessor_output& output, detail::pp_doc_comment comment)
{ {
if (output.comments.empty() || !can_merge_comment(output.comments.back(), comment.line)) if (output.comments.empty() || !can_merge_comment(output.comments.back(), comment.line))
output.comments.push_back(std::move(comment)); output.comments.push_back(std::move(comment));
else else
@ -802,10 +796,10 @@ namespace
if (result.kind != detail::pp_doc_comment::end_of_line) if (result.kind != detail::pp_doc_comment::end_of_line)
result.line = comment.line; result.line = comment.line;
} }
} }
bool skip_cpp_comment(position& p, detail::preprocessor_output& output) bool skip_cpp_comment(position& p, detail::preprocessor_output& output)
{ {
if (!starts_with(p, "//")) if (!starts_with(p, "//"))
return false; return false;
p.skip(2u); p.skip(2u);
@ -831,11 +825,11 @@ namespace
} }
return true; return true;
} }
std::unique_ptr<cpp_macro_definition> build(std::string name, ts::optional<std::string> args, std::unique_ptr<cpp_macro_definition> build(std::string name, ts::optional<std::string> args,
std::string rep) std::string rep)
{ {
if (!args) if (!args)
return cpp_macro_definition::build_object_like(std::move(name), std::move(rep)); return cpp_macro_definition::build_object_like(std::move(name), std::move(rep));
@ -859,11 +853,10 @@ namespace
} }
return builder.finish(); return builder.finish();
} }
std::unique_ptr<cpp_macro_definition> parse_macro(position& p, std::unique_ptr<cpp_macro_definition> parse_macro(position& p, detail::preprocessor_output& output)
detail::preprocessor_output& output) {
{
// format (at new line): #define <name> [replacement] // format (at new line): #define <name> [replacement]
// or: #define <name>(<args>) [replacement] // or: #define <name>(<args>) [replacement]
// note: keep macro definition in file // note: keep macro definition in file
@ -914,12 +907,13 @@ namespace
output.comments.pop_back(); output.comments.pop_back();
} }
return result; return result;
} }
ts::optional<std::string> parse_undef(position& p) ts::optional<std::string> parse_undef(position& p)
{ {
// format (at new line): #undef <name> // format (at new line): #undef <name>
// due to a clang bug (http://bugs.llvm.org/show_bug.cgi?id=32631) I'll also an undef in the middle of the line // due to a clang bug (http://bugs.llvm.org/show_bug.cgi?id=32631) I'll also an undef in the
// middle of the line
if (/*!p.was_newl() ||*/ !starts_with(p, "#undef")) if (/*!p.was_newl() ||*/ !starts_with(p, "#undef"))
return ts::nullopt; return ts::nullopt;
p.bump(std::strlen("#undef")); p.bump(std::strlen("#undef"));
@ -930,10 +924,10 @@ namespace
// don't skip newline // don't skip newline
return result; return result;
} }
type_safe::optional<detail::pp_include> parse_include(position& p) type_safe::optional<detail::pp_include> parse_include(position& p)
{ {
// format (at new line, literal <>): #include <filename> // format (at new line, literal <>): #include <filename>
// or: #include "filename" // or: #include "filename"
// note: write include back // note: write include back
@ -973,15 +967,14 @@ namespace
if (!p.write_enabled()) if (!p.write_enabled())
return type_safe::nullopt; return type_safe::nullopt;
if (filename.size() > 2u && filename[0] == '.' if (filename.size() > 2u && filename[0] == '.' && (filename[1] == '/' || filename[1] == '\\'))
&& (filename[1] == '/' || filename[1] == '\\'))
filename = filename.substr(2); filename = filename.substr(2);
return detail::pp_include{std::move(filename), "", include_kind, p.cur_line()}; return detail::pp_include{std::move(filename), "", include_kind, p.cur_line()};
} }
bool bump_pragma(position& p) bool bump_pragma(position& p)
{ {
// format (at new line): #pragma <stuff..>\n // format (at new line): #pragma <stuff..>\n
if (!p.was_newl() || !starts_with(p, "#pragma")) if (!p.was_newl() || !starts_with(p, "#pragma"))
return false; return false;
@ -991,10 +984,10 @@ namespace
// don't skip newline // don't skip newline
return true; return true;
} }
struct linemarker struct linemarker
{ {
std::string file; std::string file;
unsigned line; unsigned line;
enum enum
@ -1002,12 +995,13 @@ namespace
line_directive, // no change in file line_directive, // no change in file
enter_new, // open a new file enter_new, // open a new file
enter_old, // return to an old file enter_old, // return to an old file
} flag = line_directive; } flag
= line_directive;
bool is_system = false; bool is_system = false;
}; };
ts::optional<linemarker> parse_linemarker(position& p) ts::optional<linemarker> parse_linemarker(position& p)
{ {
// format (at new line): # <line> "<filename>" <flags> // format (at new line): # <line> "<filename>" <flags>
// flag 1: enter_new // flag 1: enter_new
// flag 2: enter_old // flag 2: enter_old
@ -1016,8 +1010,7 @@ namespace
if (!p.was_newl() || !starts_with(p, "#")) if (!p.was_newl() || !starts_with(p, "#"))
return ts::nullopt; return ts::nullopt;
p.skip(); p.skip();
DEBUG_ASSERT(!starts_with(p, "define") && !starts_with(p, "undef") DEBUG_ASSERT(!starts_with(p, "define") && !starts_with(p, "undef") && !starts_with(p, "pragma"),
&& !starts_with(p, "pragma"),
detail::assert_handler{}, "handle macros first"); detail::assert_handler{}, "handle macros first");
linemarker result; linemarker result;
@ -1065,7 +1058,7 @@ namespace
p.skip(); p.skip();
return result; return result;
} }
} // namespace } // namespace
detail::preprocessor_output detail::preprocess(const libclang_compile_config& config, detail::preprocessor_output detail::preprocess(const libclang_compile_config& config,
@ -1174,12 +1167,14 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
} }
else else
{ {
// this is an indirect include, remember it to get full path for indirect includes // this is an indirect include, remember it to get full path for indirect
// includes
auto& full_path = lm.value().file; auto& full_path = lm.value().file;
auto last_dir = full_path.find_last_of("/\\"); auto last_dir = full_path.find_last_of("/\\");
auto file_name = auto file_name = last_dir == std::string::npos
last_dir == std::string::npos ? full_path : full_path.substr(last_dir + 1u); ? full_path
: full_path.substr(last_dir + 1u);
indirect_includes.emplace(std::move(file_name), full_path); indirect_includes.emplace(std::move(file_name), full_path);
} }
@ -1237,9 +1232,9 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
{ {
auto last_sep = include.file_name.find_last_of("/\\"); auto last_sep = include.file_name.find_last_of("/\\");
auto iter = indirect_includes.find(last_sep == std::string::npos ? auto iter = indirect_includes.find(last_sep == std::string::npos
include.file_name : ? include.file_name
include.file_name.substr(last_sep + 1u)); : include.file_name.substr(last_sep + 1u));
if (iter != indirect_includes.end()) if (iter != indirect_includes.end())
include.full_path = iter->second; include.full_path = iter->second;
else else

View file

@ -10,8 +10,8 @@
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
struct pp_macro struct pp_macro
{ {
std::unique_ptr<cpp_macro_definition> macro; std::unique_ptr<cpp_macro_definition> macro;
@ -49,7 +49,7 @@ namespace cppast
preprocessor_output preprocess(const libclang_compile_config& config, const char* path, preprocessor_output preprocess(const libclang_compile_config& config, const char* path,
const diagnostic_logger& logger); const diagnostic_logger& logger);
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_PREPROCESSOR_HPP_INCLUDED #endif // CPPAST_PREPROCESSOR_HPP_INCLUDED

View file

@ -16,8 +16,8 @@
namespace cppast namespace cppast
{ {
namespace detail namespace detail
{ {
template <typename T, class Deleter> template <typename T, class Deleter>
class raii_wrapper : Deleter class raii_wrapper : Deleter
{ {
@ -144,8 +144,7 @@ namespace cppast
explicit string(CXString str) explicit string(CXString str)
: str(std::move(str)), c_str(clang_getCString(str)), length(std::strlen(c_str)) : str(std::move(str)), c_str(clang_getCString(str)), length(std::strlen(c_str))
{ {}
}
}; };
type_safe::optional<string> str_; type_safe::optional<string> str_;
}; };
@ -179,7 +178,7 @@ namespace cppast
{ {
return !(str == b); return !(str == b);
} }
} } // namespace detail
} // namespace cppast::detail } // namespace cppast
#endif // CPPAST_RAII_WRAPPER_HPP_INCLUDED #endif // CPPAST_RAII_WRAPPER_HPP_INCLUDED

View file

@ -15,10 +15,10 @@ using namespace cppast;
namespace namespace
{ {
template <typename TemplateT, typename EntityT, typename Predicate> template <typename TemplateT, typename EntityT, typename Predicate>
type_safe::optional<typename TemplateT::builder> get_builder( type_safe::optional<typename TemplateT::builder> get_builder(const detail::parse_context& context,
const detail::parse_context& context, const CXCursor& cur, Predicate p) const CXCursor& cur, Predicate p)
{ {
// we need the actual entity first, then the parameters // we need the actual entity first, then the parameters
// so two visit calls are required // so two visit calls are required
@ -38,15 +38,14 @@ namespace
auto entity = detail::parse_entity(context, nullptr, result, cur); auto entity = detail::parse_entity(context, nullptr, result, cur);
if (!entity) if (!entity)
return type_safe::nullopt; return type_safe::nullopt;
DEBUG_ASSERT(p(entity->kind()), detail::parse_error_handler{}, cur, DEBUG_ASSERT(p(entity->kind()), detail::parse_error_handler{}, cur, "wrong child of template");
"wrong child of template");
return typename TemplateT::builder( return typename TemplateT::builder(
std::unique_ptr<EntityT>(static_cast<EntityT*>(entity.release()))); std::unique_ptr<EntityT>(static_cast<EntityT*>(entity.release())));
} }
std::unique_ptr<cpp_template_parameter> parse_type_parameter( std::unique_ptr<cpp_template_parameter> parse_type_parameter(const detail::parse_context& context,
const detail::parse_context& context, const CXCursor& cur) const CXCursor& cur)
{ {
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TemplateTypeParameter, DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TemplateTypeParameter,
detail::assert_handler{}); detail::assert_handler{});
@ -75,11 +74,11 @@ namespace
return cpp_template_type_parameter::build(*context.idx, detail::get_entity_id(cur), return cpp_template_type_parameter::build(*context.idx, detail::get_entity_id(cur),
name.c_str(), keyword, variadic, std::move(def)); name.c_str(), keyword, variadic, std::move(def));
} }
std::unique_ptr<cpp_template_parameter> parse_non_type_parameter( std::unique_ptr<cpp_template_parameter> parse_non_type_parameter(
const detail::parse_context& context, const CXCursor& cur) const detail::parse_context& context, const CXCursor& cur)
{ {
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_NonTypeTemplateParameter, DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_NonTypeTemplateParameter,
detail::assert_handler{}); detail::assert_handler{});
@ -110,18 +109,17 @@ namespace
break; break;
} }
auto result = auto result = cpp_non_type_template_parameter::build(*context.idx, detail::get_entity_id(cur),
cpp_non_type_template_parameter::build(*context.idx, detail::get_entity_id(cur),
name.c_str(), name.c_str(),
detail::parse_type(context, cur, type), detail::parse_type(context, cur, type),
is_variadic, std::move(def)); is_variadic, std::move(def));
result->add_attribute(attributes); result->add_attribute(attributes);
return std::move(result); return std::move(result);
} }
std::unique_ptr<cpp_template_template_parameter> parse_template_parameter( std::unique_ptr<cpp_template_template_parameter> parse_template_parameter(
const detail::parse_context& context, const CXCursor& cur) const detail::parse_context& context, const CXCursor& cur)
{ {
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TemplateTemplateParameter, DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TemplateTemplateParameter,
detail::assert_handler{}); detail::assert_handler{});
@ -168,11 +166,9 @@ namespace
spelling += stream.get().c_str(); spelling += stream.get().c_str();
if (stream.unmunch()) if (stream.unmunch())
{ {
DEBUG_ASSERT(!spelling.empty() && spelling.back() == '>', DEBUG_ASSERT(!spelling.empty() && spelling.back() == '>', detail::assert_handler{});
detail::assert_handler{});
spelling.pop_back(); spelling.pop_back();
DEBUG_ASSERT(!spelling.empty() && spelling.back() == '>', DEBUG_ASSERT(!spelling.empty() && spelling.back() == '>', detail::assert_handler{});
detail::assert_handler{});
} }
builder.default_template( builder.default_template(
@ -184,12 +180,11 @@ namespace
}); });
return builder.finish(*context.idx, detail::get_entity_id(cur)); return builder.finish(*context.idx, detail::get_entity_id(cur));
} }
template <class Builder> template <class Builder>
void parse_parameters(Builder& builder, const detail::parse_context& context, void parse_parameters(Builder& builder, const detail::parse_context& context, const CXCursor& cur)
const CXCursor& cur) {
{
// now visit to get the parameters // now visit to get the parameters
detail::visit_children(cur, [&](const CXCursor& child) { detail::visit_children(cur, [&](const CXCursor& child) {
auto kind = clang_getCursorKind(child); auto kind = clang_getCursorKind(child);
@ -200,10 +195,10 @@ namespace
else if (kind == CXCursor_TemplateTemplateParameter) else if (kind == CXCursor_TemplateTemplateParameter)
builder.add_parameter(parse_template_parameter(context, child)); builder.add_parameter(parse_template_parameter(context, child));
}); });
} }
void handle_comment_attributes(cpp_entity& templ_entity, cpp_entity& non_template) void handle_comment_attributes(cpp_entity& templ_entity, cpp_entity& non_template)
{ {
// steal comment // steal comment
auto comment = type_safe::copy(non_template.comment()); auto comment = type_safe::copy(non_template.comment());
non_template.set_comment(type_safe::nullopt); non_template.set_comment(type_safe::nullopt);
@ -211,16 +206,16 @@ namespace
// copy attributes over // copy attributes over
templ_entity.add_attribute(non_template.attributes()); templ_entity.add_attribute(non_template.attributes());
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::parse_cpp_alias_template(const detail::parse_context& context, std::unique_ptr<cpp_entity> detail::parse_cpp_alias_template(const detail::parse_context& context,
const CXCursor& cur) const CXCursor& cur)
{ {
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TypeAliasTemplateDecl, DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TypeAliasTemplateDecl,
detail::assert_handler{}); detail::assert_handler{});
auto builder = auto builder
get_builder<cpp_alias_template, cpp_type_alias>(context, cur, [](cpp_entity_kind k) { = get_builder<cpp_alias_template, cpp_type_alias>(context, cur, [](cpp_entity_kind k) {
return k == cpp_entity_kind::type_alias_t; return k == cpp_entity_kind::type_alias_t;
}); });
if (!builder) if (!builder)
@ -274,14 +269,13 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_function_template(
namespace namespace
{ {
template <class Builder> template <class Builder>
void parse_arguments(Builder& b, const detail::parse_context& context, const CXCursor& cur) void parse_arguments(Builder& b, const detail::parse_context& context, const CXCursor& cur)
{ {
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
detail::cxtoken_stream stream(tokenizer, cur); detail::cxtoken_stream stream(tokenizer, cur);
while (!stream.done() while (!stream.done() && !detail::skip_if(stream, detail::get_cursor_name(cur).c_str(), true))
&& !detail::skip_if(stream, detail::get_cursor_name(cur).c_str(), true))
stream.bump(); stream.bump();
if (stream.peek() == "<") if (stream.peek() == "<")
@ -294,8 +288,8 @@ namespace
} }
else else
b.add_unexposed_arguments(cpp_token_string::builder().finish()); b.add_unexposed_arguments(cpp_token_string::builder().finish());
}
} }
} // namespace
std::unique_ptr<cpp_entity> detail::try_parse_cpp_function_template_specialization( std::unique_ptr<cpp_entity> detail::try_parse_cpp_function_template_specialization(
const detail::parse_context& context, const CXCursor& cur, bool is_friend) const detail::parse_context& context, const CXCursor& cur, bool is_friend)

View file

@ -21,20 +21,20 @@ using namespace cppast;
namespace namespace
{ {
void remove_trailing_ws(std::string& str) void remove_trailing_ws(std::string& str)
{ {
while (!str.empty() && std::isspace(str.back())) while (!str.empty() && std::isspace(str.back()))
str.pop_back(); str.pop_back();
} }
void remove_leading_ws(std::string& str) void remove_leading_ws(std::string& str)
{ {
while (!str.empty() && std::isspace(str.front())) while (!str.empty() && std::isspace(str.front()))
str.erase(0, 1); str.erase(0, 1);
} }
bool can_extend_suffix(const std::string& str, std::size_t suffix_length) bool can_extend_suffix(const std::string& str, std::size_t suffix_length)
{ {
if (str.length() <= suffix_length + 1u) if (str.length() <= suffix_length + 1u)
{ {
auto c = str[str.length() - suffix_length - 1u]; auto c = str[str.length() - suffix_length - 1u];
@ -42,11 +42,11 @@ namespace
} }
else else
return false; return false;
} }
// if identifier only removes maximal suffix according to tokenization // if identifier only removes maximal suffix according to tokenization
bool remove_suffix(std::string& str, const char* suffix, bool is_identifier) bool remove_suffix(std::string& str, const char* suffix, bool is_identifier)
{ {
auto length = std::strlen(suffix); auto length = std::strlen(suffix);
if (str.length() >= length && str.compare(str.length() - length, length, suffix) == 0 if (str.length() >= length && str.compare(str.length() - length, length, suffix) == 0
&& (!is_identifier || !can_extend_suffix(str, length))) && (!is_identifier || !can_extend_suffix(str, length)))
@ -57,10 +57,10 @@ namespace
} }
else else
return false; return false;
} }
bool can_extend_prefix(const std::string& str, std::size_t prefix_length) bool can_extend_prefix(const std::string& str, std::size_t prefix_length)
{ {
if (prefix_length < str.size()) if (prefix_length < str.size())
{ {
auto c = str[prefix_length]; auto c = str[prefix_length];
@ -68,11 +68,11 @@ namespace
} }
else else
return false; return false;
} }
// if identifier only removes maximal suffix according to tokenization // if identifier only removes maximal suffix according to tokenization
bool remove_prefix(std::string& str, const char* prefix, bool is_identifier) bool remove_prefix(std::string& str, const char* prefix, bool is_identifier)
{ {
auto length = std::strlen(prefix); auto length = std::strlen(prefix);
if (str.length() >= length && str.compare(0u, length, prefix) == 0 if (str.length() >= length && str.compare(0u, length, prefix) == 0
&& (!is_identifier || !can_extend_prefix(str, length))) && (!is_identifier || !can_extend_prefix(str, length)))
@ -83,10 +83,10 @@ namespace
} }
else else
return false; return false;
} }
bool need_to_remove_scope(const CXCursor& cur, const CXType& type) bool need_to_remove_scope(const CXCursor& cur, const CXType& type)
{ {
if (type.kind != CXType_Typedef) if (type.kind != CXType_Typedef)
return false; return false;
@ -95,10 +95,10 @@ namespace
auto parent = clang_getCursorSemanticParent(cur); auto parent = clang_getCursorSemanticParent(cur);
auto decl_parent = clang_getCursorSemanticParent(clang_getTypeDeclaration(type)); auto decl_parent = clang_getCursorSemanticParent(clang_getTypeDeclaration(type));
return clang_equalCursors(parent, decl_parent) != 0; return clang_equalCursors(parent, decl_parent) != 0;
} }
std::string get_type_spelling(const CXCursor& cur, const CXType& type) std::string get_type_spelling(const CXCursor& cur, const CXType& type)
{ {
auto spelling = detail::cxstring(clang_getTypeSpelling(type)).std_str(); auto spelling = detail::cxstring(clang_getTypeSpelling(type)).std_str();
if (need_to_remove_scope(cur, type)) if (need_to_remove_scope(cur, type))
{ {
@ -108,12 +108,12 @@ namespace
} }
return spelling; return spelling;
} }
// const/volatile at the end (because people do that apparently!) // const/volatile at the end (because people do that apparently!)
// also used on member function pointers // also used on member function pointers
cpp_cv suffix_cv(std::string& spelling) cpp_cv suffix_cv(std::string& spelling)
{ {
auto cv = cpp_cv_none; auto cv = cpp_cv_none;
if (remove_suffix(spelling, "const", true)) if (remove_suffix(spelling, "const", true))
{ {
@ -131,11 +131,11 @@ namespace
} }
return cv; return cv;
} }
// const/volatile at the beginning // const/volatile at the beginning
cpp_cv prefix_cv(std::string& spelling) cpp_cv prefix_cv(std::string& spelling)
{ {
auto cv = cpp_cv_none; auto cv = cpp_cv_none;
if (remove_prefix(spelling, "const", true)) if (remove_prefix(spelling, "const", true))
{ {
@ -153,10 +153,10 @@ namespace
} }
return cv; return cv;
} }
cpp_cv merge_cv(cpp_cv a, cpp_cv b) cpp_cv merge_cv(cpp_cv a, cpp_cv b)
{ {
switch (a) switch (a)
{ {
case cpp_cv_none: case cpp_cv_none:
@ -196,18 +196,18 @@ namespace
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return cpp_cv_none; return cpp_cv_none;
} }
std::unique_ptr<cpp_type> make_cv_qualified(std::unique_ptr<cpp_type> entity, cpp_cv cv) std::unique_ptr<cpp_type> make_cv_qualified(std::unique_ptr<cpp_type> entity, cpp_cv cv)
{ {
if (cv == cpp_cv_none) if (cv == cpp_cv_none)
return entity; return entity;
return cpp_cv_qualified_type::build(std::move(entity), cv); return cpp_cv_qualified_type::build(std::move(entity), cv);
} }
template <typename Builder> template <typename Builder>
std::unique_ptr<cpp_type> make_leave_type(const CXCursor& cur, const CXType& type, Builder b) std::unique_ptr<cpp_type> make_leave_type(const CXCursor& cur, const CXType& type, Builder b)
{ {
auto spelling = get_type_spelling(cur, type); auto spelling = get_type_spelling(cur, type);
// check for cv qualifiers on the leave type // check for cv qualifiers on the leave type
@ -225,22 +225,22 @@ namespace
if (!entity) if (!entity)
return nullptr; return nullptr;
return make_cv_qualified(std::move(entity), cv); return make_cv_qualified(std::move(entity), cv);
} }
cpp_reference get_reference_kind(const CXType& type) cpp_reference get_reference_kind(const CXType& type)
{ {
if (type.kind == CXType_LValueReference) if (type.kind == CXType_LValueReference)
return cpp_ref_lvalue; return cpp_ref_lvalue;
else if (type.kind == CXType_RValueReference) else if (type.kind == CXType_RValueReference)
return cpp_ref_rvalue; return cpp_ref_rvalue;
return cpp_ref_none; return cpp_ref_none;
} }
std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context, std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context, const CXCursor& cur,
const CXCursor& cur, const CXType& type); const CXType& type);
std::unique_ptr<cpp_expression> parse_array_size(const CXCursor& cur, const CXType& type) std::unique_ptr<cpp_expression> parse_array_size(const CXCursor& cur, const CXType& type)
{ {
auto size = clang_getArraySize(type); auto size = clang_getArraySize(type);
if (size != -1) if (size != -1)
return cpp_literal_expression::build(cpp_builtin_type::build(cpp_ulonglong), return cpp_literal_expression::build(cpp_builtin_type::build(cpp_ulonglong),
@ -263,17 +263,17 @@ namespace
size_expr += *ptr; size_expr += *ptr;
} }
return size_expr.empty() ? return size_expr.empty()
nullptr : ? nullptr
cpp_unexposed_expression::build(cpp_builtin_type::build(cpp_ulonglong), : cpp_unexposed_expression::build(cpp_builtin_type::build(cpp_ulonglong),
cpp_token_string::tokenize( cpp_token_string::tokenize(
std::string(size_expr.rbegin(), std::string(size_expr.rbegin(),
size_expr.rend()))); size_expr.rend())));
} }
std::unique_ptr<cpp_type> try_parse_array_type(const detail::parse_context& context, std::unique_ptr<cpp_type> try_parse_array_type(const detail::parse_context& context,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
auto canonical = clang_getCanonicalType(type); auto canonical = clang_getCanonicalType(type);
auto value_type = clang_getArrayElementType(type); auto value_type = clang_getArrayElementType(type);
if (value_type.kind == CXType_Invalid) if (value_type.kind == CXType_Invalid)
@ -291,15 +291,14 @@ namespace
auto size = parse_array_size(cur, canonical); // type may not work, see above auto size = parse_array_size(cur, canonical); // type may not work, see above
return cpp_array_type::build(parse_type_impl(context, cur, value_type), std::move(size)); return cpp_array_type::build(parse_type_impl(context, cur, value_type), std::move(size));
} }
template <class Builder> template <class Builder>
std::unique_ptr<cpp_type> add_parameters(Builder& builder, const detail::parse_context& context, std::unique_ptr<cpp_type> add_parameters(Builder& builder, const detail::parse_context& context,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
auto no_args = clang_getNumArgTypes(type); auto no_args = clang_getNumArgTypes(type);
DEBUG_ASSERT(no_args >= 0, detail::parse_error_handler{}, type, DEBUG_ASSERT(no_args >= 0, detail::parse_error_handler{}, type, "invalid number of arguments");
"invalid number of arguments");
for (auto i = 0u; i != unsigned(no_args); ++i) for (auto i = 0u; i != unsigned(no_args); ++i)
builder.add_parameter(parse_type_impl(context, cur, clang_getArgType(type, i))); builder.add_parameter(parse_type_impl(context, cur, clang_getArgType(type, i)));
@ -307,11 +306,11 @@ namespace
builder.is_variadic(); builder.is_variadic();
return builder.finish(); return builder.finish();
} }
std::unique_ptr<cpp_type> try_parse_function_type(const detail::parse_context& context, std::unique_ptr<cpp_type> try_parse_function_type(const detail::parse_context& context,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
auto result = clang_getResultType(type); auto result = clang_getResultType(type);
if (result.kind == CXType_Invalid) if (result.kind == CXType_Invalid)
// not a function type // not a function type
@ -319,34 +318,34 @@ namespace
cpp_function_type::builder builder(parse_type_impl(context, cur, result)); cpp_function_type::builder builder(parse_type_impl(context, cur, result));
return add_parameters(builder, context, cur, type); return add_parameters(builder, context, cur, type);
} }
cpp_reference member_function_ref_qualifier(std::string& spelling) cpp_reference member_function_ref_qualifier(std::string& spelling)
{ {
if (remove_suffix(spelling, "&&", false)) if (remove_suffix(spelling, "&&", false))
return cpp_ref_rvalue; return cpp_ref_rvalue;
else if (remove_suffix(spelling, "&", false)) else if (remove_suffix(spelling, "&", false))
return cpp_ref_lvalue; return cpp_ref_lvalue;
return cpp_ref_none; return cpp_ref_none;
} }
std::unique_ptr<cpp_type> make_ref_qualified(std::unique_ptr<cpp_type> type, cpp_reference ref) std::unique_ptr<cpp_type> make_ref_qualified(std::unique_ptr<cpp_type> type, cpp_reference ref)
{ {
if (ref == cpp_ref_none) if (ref == cpp_ref_none)
return type; return type;
return cpp_reference_type::build(std::move(type), ref); return cpp_reference_type::build(std::move(type), ref);
} }
std::unique_ptr<cpp_type> parse_member_pointee_type(const detail::parse_context& context, std::unique_ptr<cpp_type> parse_member_pointee_type(const detail::parse_context& context,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
auto spelling = get_type_spelling(cur, type); auto spelling = get_type_spelling(cur, type);
auto ref = member_function_ref_qualifier(spelling); auto ref = member_function_ref_qualifier(spelling);
auto cv = suffix_cv(spelling); auto cv = suffix_cv(spelling);
auto class_t = clang_Type_getClassType(type); auto class_t = clang_Type_getClassType(type);
auto class_entity = auto class_entity
make_ref_qualified(make_cv_qualified(parse_type_impl(context, cur, class_t), cv), ref); = make_ref_qualified(make_cv_qualified(parse_type_impl(context, cur, class_t), cv), ref);
auto pointee = clang_getPointeeType(type); // for everything except the class type auto pointee = clang_getPointeeType(type); // for everything except the class type
auto result = clang_getResultType(pointee); auto result = clang_getResultType(pointee);
@ -362,27 +361,27 @@ namespace
parse_type_impl(context, cur, result)); parse_type_impl(context, cur, result));
return add_parameters(builder, context, cur, pointee); return add_parameters(builder, context, cur, pointee);
} }
} }
bool is_direct_templated(const CXCursor& cur) bool is_direct_templated(const CXCursor& cur)
{ {
// TODO: variable template // TODO: variable template
auto kind = clang_getCursorKind(cur); auto kind = clang_getCursorKind(cur);
return kind == CXCursor_TypeAliasTemplateDecl || kind == CXCursor_ClassTemplate return kind == CXCursor_TypeAliasTemplateDecl || kind == CXCursor_ClassTemplate
|| kind == CXCursor_ClassTemplatePartialSpecialization || kind == CXCursor_ClassTemplatePartialSpecialization
|| kind == CXCursor_FunctionTemplate; || kind == CXCursor_FunctionTemplate;
} }
bool check_parent(const CXCursor& parent) bool check_parent(const CXCursor& parent)
{ {
if (clang_Cursor_isNull(parent)) if (clang_Cursor_isNull(parent))
return false; return false;
auto kind = clang_getCursorKind(parent); auto kind = clang_getCursorKind(parent);
return kind != CXCursor_Namespace && kind != CXCursor_TranslationUnit; return kind != CXCursor_Namespace && kind != CXCursor_TranslationUnit;
} }
CXCursor get_template(CXCursor cur) CXCursor get_template(CXCursor cur)
{ {
do do
{ {
if (is_direct_templated(cur)) if (is_direct_templated(cur))
@ -390,11 +389,11 @@ namespace
cur = clang_getCursorSemanticParent(cur); cur = clang_getCursorSemanticParent(cur);
} while (check_parent(cur)); } while (check_parent(cur));
return clang_getNullCursor(); return clang_getNullCursor();
} }
std::unique_ptr<cpp_type> try_parse_template_parameter_type( std::unique_ptr<cpp_type> try_parse_template_parameter_type(const detail::parse_context& context,
const detail::parse_context& context, const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
// see if we have a parent template // see if we have a parent template
auto templ = get_template(cur); auto templ = get_template(cur);
if (clang_Cursor_isNull(templ)) if (clang_Cursor_isNull(templ))
@ -402,20 +401,17 @@ namespace
return nullptr; return nullptr;
// doesn't respect cv qualifiers properly // doesn't respect cv qualifiers properly
auto result = auto result
make_leave_type(cur, type, = make_leave_type(cur, type, [&](std::string&& type_spelling) -> std::unique_ptr<cpp_type> {
[&](std::string&& type_spelling) -> std::unique_ptr<cpp_type> {
// look at the template parameters, // look at the template parameters,
// see if we find a matching one // see if we find a matching one
auto param = clang_getNullCursor(); auto param = clang_getNullCursor();
detail::visit_children(templ, [&](const CXCursor& child) { detail::visit_children(templ, [&](const CXCursor& child) {
if (clang_getCursorKind(child) == CXCursor_TemplateTypeParameter if (clang_getCursorKind(child) == CXCursor_TemplateTypeParameter
&& get_type_spelling(child, clang_getCursorType(child)) && get_type_spelling(child, clang_getCursorType(child)) == type_spelling)
== type_spelling)
{ {
// found one // found one
DEBUG_ASSERT(clang_Cursor_isNull(param), DEBUG_ASSERT(clang_Cursor_isNull(param), detail::assert_handler{});
detail::assert_handler{});
param = child; param = child;
} }
}); });
@ -425,8 +421,7 @@ namespace
else else
// found matching parameter // found matching parameter
return cpp_template_parameter_type::build( return cpp_template_parameter_type::build(
cpp_template_type_parameter_ref(detail::get_entity_id( cpp_template_type_parameter_ref(detail::get_entity_id(param),
param),
std::move(type_spelling))); std::move(type_spelling)));
}); });
@ -436,11 +431,11 @@ namespace
// try again in a possible parent template // try again in a possible parent template
return try_parse_template_parameter_type(context, clang_getCursorSemanticParent(templ), return try_parse_template_parameter_type(context, clang_getCursorSemanticParent(templ),
type); type);
} }
CXCursor get_instantiation_template(const CXCursor& cur, const CXType& type, CXCursor get_instantiation_template(const CXCursor& cur, const CXType& type,
const std::string& templ_name) const std::string& templ_name)
{ {
// look if the type has a declaration that is a template // look if the type has a declaration that is a template
auto decl = clang_getTypeDeclaration(type); auto decl = clang_getTypeDeclaration(type);
auto count = clang_Type_getNumTemplateArguments(clang_getCursorType(decl)); auto count = clang_Type_getNumTemplateArguments(clang_getCursorType(decl));
@ -468,11 +463,11 @@ namespace
}); });
return param; return param;
} }
} }
std::unique_ptr<cpp_type> try_parse_instantiation_type(const detail::parse_context&, std::unique_ptr<cpp_type> try_parse_instantiation_type(const detail::parse_context&,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
{ {
return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> { return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> {
auto ptr = spelling.c_str(); auto ptr = spelling.c_str();
@ -501,11 +496,11 @@ namespace
return builder.finish(); return builder.finish();
}); });
} }
std::unique_ptr<cpp_type> try_parse_decltype_type(const detail::parse_context&, std::unique_ptr<cpp_type> try_parse_decltype_type(const detail::parse_context&, const CXCursor& cur,
const CXCursor& cur, const CXType& type) const CXType& type)
{ {
if (clang_isExpression(clang_getCursorKind(cur))) if (clang_isExpression(clang_getCursorKind(cur)))
return nullptr; // don't use decltype here return nullptr; // don't use decltype here
@ -521,11 +516,11 @@ namespace
cpp_unexposed_expression::build(cpp_unexposed_type::build("<decltype>"), cpp_unexposed_expression::build(cpp_unexposed_type::build("<decltype>"),
cpp_token_string::tokenize(spelling))); cpp_token_string::tokenize(spelling)));
}); });
} }
std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context, std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context, const CXCursor& cur,
const CXCursor& cur, const CXType& type) const CXType& type)
{ {
switch (type.kind) switch (type.kind)
{ {
// stuff I can't parse // stuff I can't parse
@ -589,10 +584,10 @@ namespace
context.logger->log("libclang parser", context.logger->log("libclang parser",
format_diagnostic(severity::warning, detail::make_location(type), format_diagnostic(severity::warning, detail::make_location(type),
"unexpected type of kind '", "unexpected type of kind '",
detail::get_type_kind_spelling(type).c_str(), detail::get_type_kind_spelling(type).c_str(), "'"));
"'"));
// fallthrough // fallthrough
case CXType_Dependent: // seems to have something to do with expressions, just ignore that (for now?) case CXType_Dependent: // seems to have something to do with expressions, just ignore that (for
// now?)
case CXType_Unexposed: case CXType_Unexposed:
if (auto ftype = try_parse_function_type(context, cur, type)) if (auto ftype = try_parse_function_type(context, cur, type))
// guess what: after you've called clang_getPointeeType() on a function pointer // guess what: after you've called clang_getPointeeType() on a function pointer
@ -621,36 +616,30 @@ namespace
return make_leave_type(cur, type, return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_bool); }); [](std::string&&) { return cpp_builtin_type::build(cpp_bool); });
case CXType_UChar: case CXType_UChar:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_uchar); [](std::string&&) { return cpp_builtin_type::build(cpp_uchar); });
});
case CXType_UShort: case CXType_UShort:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_ushort); [](std::string&&) { return cpp_builtin_type::build(cpp_ushort); });
});
case CXType_UInt: case CXType_UInt:
return make_leave_type(cur, type, return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_uint); }); [](std::string&&) { return cpp_builtin_type::build(cpp_uint); });
case CXType_ULong: case CXType_ULong:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_ulong); [](std::string&&) { return cpp_builtin_type::build(cpp_ulong); });
});
case CXType_ULongLong: case CXType_ULongLong:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_ulonglong); return cpp_builtin_type::build(cpp_ulonglong);
}); });
case CXType_UInt128: case CXType_UInt128:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_uint128); [](std::string&&) { return cpp_builtin_type::build(cpp_uint128); });
});
case CXType_SChar: case CXType_SChar:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_schar); [](std::string&&) { return cpp_builtin_type::build(cpp_schar); });
});
case CXType_Short: case CXType_Short:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_short); [](std::string&&) { return cpp_builtin_type::build(cpp_short); });
});
case CXType_Int: case CXType_Int:
return make_leave_type(cur, type, return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_int); }); [](std::string&&) { return cpp_builtin_type::build(cpp_int); });
@ -658,49 +647,40 @@ namespace
return make_leave_type(cur, type, return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_long); }); [](std::string&&) { return cpp_builtin_type::build(cpp_long); });
case CXType_LongLong: case CXType_LongLong:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_longlong); [](std::string&&) { return cpp_builtin_type::build(cpp_longlong); });
});
case CXType_Int128: case CXType_Int128:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_int128); [](std::string&&) { return cpp_builtin_type::build(cpp_int128); });
});
case CXType_Float: case CXType_Float:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_float); [](std::string&&) { return cpp_builtin_type::build(cpp_float); });
});
case CXType_Double: case CXType_Double:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_double); [](std::string&&) { return cpp_builtin_type::build(cpp_double); });
});
case CXType_LongDouble: case CXType_LongDouble:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_longdouble); return cpp_builtin_type::build(cpp_longdouble);
}); });
case CXType_Float128: case CXType_Float128:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_float128); [](std::string&&) { return cpp_builtin_type::build(cpp_float128); });
});
case CXType_Char_U: case CXType_Char_U:
case CXType_Char_S: case CXType_Char_S:
return make_leave_type(cur, type, return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_char); }); [](std::string&&) { return cpp_builtin_type::build(cpp_char); });
case CXType_Char16: case CXType_Char16:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_char16); [](std::string&&) { return cpp_builtin_type::build(cpp_char16); });
});
case CXType_Char32: case CXType_Char32:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_char32); [](std::string&&) { return cpp_builtin_type::build(cpp_char32); });
});
case CXType_WChar: case CXType_WChar:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_wchar); [](std::string&&) { return cpp_builtin_type::build(cpp_wchar); });
});
case CXType_NullPtr: case CXType_NullPtr:
return make_leave_type(cur, type, [](std::string&&) { return make_leave_type(cur, type,
return cpp_builtin_type::build(cpp_nullptr); [](std::string&&) { return cpp_builtin_type::build(cpp_nullptr); });
});
case CXType_Elaborated: case CXType_Elaborated:
if (auto itype = try_parse_instantiation_type(context, cur, type)) if (auto itype = try_parse_instantiation_type(context, cur, type))
@ -748,14 +728,13 @@ namespace
return cpp_pointer_type::build(parse_member_pointee_type(context, cur, type)); return cpp_pointer_type::build(parse_member_pointee_type(context, cur, type));
case CXType_Auto: case CXType_Auto:
return make_leave_type(cur, type, return make_leave_type(cur, type, [&](std::string&&) { return cpp_auto_type::build(); });
[&](std::string&&) { return cpp_auto_type::build(); });
} }
DEBUG_UNREACHABLE(detail::assert_handler{}); DEBUG_UNREACHABLE(detail::assert_handler{});
return nullptr; return nullptr;
}
} }
} // namespace
std::unique_ptr<cpp_type> detail::parse_type(const detail::parse_context& context, std::unique_ptr<cpp_type> detail::parse_type(const detail::parse_context& context,
const CXCursor& cur, const CXType& type) const CXCursor& cur, const CXType& type)
@ -789,8 +768,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_type_alias(const detail::parse_con
result = cpp_type_alias::build(name.c_str(), std::move(type)); result = cpp_type_alias::build(name.c_str(), std::move(type));
else else
{ {
result = result = cpp_type_alias::build(*context.idx, get_entity_id(cur), name.c_str(),
cpp_type_alias::build(*context.idx, get_entity_id(cur), name.c_str(), std::move(type)); std::move(type));
context.comments.match(*result, cur); context.comments.match(*result, cur);
} }

View file

@ -64,8 +64,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_variable(const detail::parse_conte
detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtokenizer tokenizer(context.tu, context.file, cur);
for (auto& token : tokenizer) for (auto& token : tokenizer)
if (token.value() == "thread_local") if (token.value() == "thread_local")
storage_class = storage_class
cpp_storage_class_specifiers(storage_class | cpp_storage_class_thread_local); = cpp_storage_class_specifiers(storage_class | cpp_storage_class_thread_local);
else if (token.value() == "constexpr") else if (token.value() == "constexpr")
is_constexpr = true; is_constexpr = true;
@ -75,8 +75,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_variable(const detail::parse_conte
std::unique_ptr<cpp_variable> result; std::unique_ptr<cpp_variable> result;
if (clang_isCursorDefinition(cur)) if (clang_isCursorDefinition(cur))
{ {
result = result
cpp_variable::build(*context.idx, get_entity_id(cur), name.c_str(), std::move(type), = cpp_variable::build(*context.idx, get_entity_id(cur), name.c_str(), std::move(type),
std::move(default_value), storage_class, is_constexpr); std::move(default_value), storage_class, is_constexpr);
} }
else else

View file

@ -18,29 +18,29 @@ using namespace cppast;
namespace namespace
{ {
cpp_access_specifier_kind get_initial_access(const cpp_entity& e) cpp_access_specifier_kind get_initial_access(const cpp_entity& e)
{ {
if (e.kind() == cpp_class::kind()) if (e.kind() == cpp_class::kind())
return static_cast<const cpp_class&>(e).class_kind() == cpp_class_kind::class_t ? return static_cast<const cpp_class&>(e).class_kind() == cpp_class_kind::class_t
cpp_private : ? cpp_private
cpp_public; : cpp_public;
return cpp_public; return cpp_public;
} }
void update_access(cpp_access_specifier_kind& child_access, const cpp_entity& child) void update_access(cpp_access_specifier_kind& child_access, const cpp_entity& child)
{ {
if (child.kind() == cpp_access_specifier::kind()) if (child.kind() == cpp_access_specifier::kind())
child_access = static_cast<const cpp_access_specifier&>(child).access_specifier(); child_access = static_cast<const cpp_access_specifier&>(child).access_specifier();
} }
template <typename T> template <typename T>
bool handle_container(const cpp_entity& e, detail::visitor_callback_t cb, void* functor, bool handle_container(const cpp_entity& e, detail::visitor_callback_t cb, void* functor,
cpp_access_specifier_kind cur_access, bool last_child) cpp_access_specifier_kind cur_access, bool last_child)
{ {
auto& container = static_cast<const T&>(e); auto& container = static_cast<const T&>(e);
auto handle_children = auto handle_children
cb(functor, container, {visitor_info::container_entity_enter, cur_access, last_child}); = cb(functor, container, {visitor_info::container_entity_enter, cur_access, last_child});
if (handle_children) if (handle_children)
{ {
auto child_access = get_initial_access(e); auto child_access = get_initial_access(e);
@ -56,9 +56,8 @@ namespace
} }
} }
return cb(functor, container, return cb(functor, container, {visitor_info::container_entity_exit, cur_access, last_child});
{visitor_info::container_entity_exit, cur_access, last_child}); }
}
} // namespace } // namespace
bool detail::visit(const cpp_entity& e, detail::visitor_callback_t cb, void* functor, bool detail::visit(const cpp_entity& e, detail::visitor_callback_t cb, void* functor,

View file

@ -46,9 +46,9 @@ alignas(type) int var;
auto file = parse({}, "cpp_attribute.cpp", code); auto file = parse({}, "cpp_attribute.cpp", code);
auto check_attribute = [](const cpp_attribute& attr, const char* name, auto check_attribute
type_safe::optional<std::string> scope, bool variadic, = [](const cpp_attribute& attr, const char* name, type_safe::optional<std::string> scope,
const char* args, cpp_attribute_kind kind) { bool variadic, const char* args, cpp_attribute_kind kind) {
REQUIRE(attr.kind() == kind); REQUIRE(attr.kind() == kind);
REQUIRE(attr.name() == name); REQUIRE(attr.name() == name);
REQUIRE(attr.scope() == scope); REQUIRE(attr.scope() == scope);
@ -60,8 +60,8 @@ alignas(type) int var;
REQUIRE(*args == '\0'); REQUIRE(*args == '\0');
}; };
auto count = auto count
test_visit<cpp_function>(*file, = test_visit<cpp_function>(*file,
[&](const cpp_entity& e) { [&](const cpp_entity& e) {
auto& attributes = e.attributes(); auto& attributes = e.attributes();
REQUIRE(attributes.size() >= 1u); REQUIRE(attributes.size() >= 1u);
@ -79,8 +79,8 @@ alignas(type) int var;
cpp_attribute_kind::unknown); cpp_attribute_kind::unknown);
} }
else if (e.name() == "c") else if (e.name() == "c")
check_attribute(attr, "variadic", type_safe::nullopt, true, check_attribute(attr, "variadic", type_safe::nullopt,
"", cpp_attribute_kind::unknown); true, "", cpp_attribute_kind::unknown);
else if (e.name() == "d") else if (e.name() == "d")
{ {
REQUIRE(has_attribute(e, "ns::attribute")); REQUIRE(has_attribute(e, "ns::attribute"));
@ -94,17 +94,19 @@ alignas(type) int var;
else if (e.name() == "f") else if (e.name() == "f")
{ {
REQUIRE(attributes.size() == 2u); REQUIRE(attributes.size() == 2u);
check_attribute(attr, "attribute", "ns", false, "+,-,0 4", check_attribute(attr, "attribute", "ns", false,
cpp_attribute_kind::unknown); "+,-,0 4", cpp_attribute_kind::unknown);
check_attribute(attributes[1u], "other_attribute", check_attribute(attributes[1u], "other_attribute",
type_safe::nullopt, false, "", type_safe::nullopt, false, "",
cpp_attribute_kind::unknown); cpp_attribute_kind::unknown);
} }
else if (e.name() == "g") else if (e.name() == "g")
{ {
REQUIRE(has_attribute(e, cpp_attribute_kind::deprecated)); REQUIRE(
has_attribute(e, cpp_attribute_kind::deprecated));
check_attribute(attr, "deprecated", type_safe::nullopt, check_attribute(attr, "deprecated", type_safe::nullopt,
false, "", cpp_attribute_kind::deprecated); false, "",
cpp_attribute_kind::deprecated);
} }
else if (e.name() == "h") else if (e.name() == "h")
check_attribute(attr, "maybe_unused", type_safe::nullopt, check_attribute(attr, "maybe_unused", type_safe::nullopt,
@ -112,7 +114,8 @@ alignas(type) int var;
cpp_attribute_kind::maybe_unused); cpp_attribute_kind::maybe_unused);
else if (e.name() == "i") else if (e.name() == "i")
check_attribute(attr, "nodiscard", type_safe::nullopt, check_attribute(attr, "nodiscard", type_safe::nullopt,
false, "", cpp_attribute_kind::nodiscard); false, "",
cpp_attribute_kind::nodiscard);
else if (e.name() == "j") else if (e.name() == "j")
check_attribute(attr, "noreturn", type_safe::nullopt, check_attribute(attr, "noreturn", type_safe::nullopt,
false, "", cpp_attribute_kind::noreturn); false, "", cpp_attribute_kind::noreturn);

View file

@ -226,8 +226,8 @@ int d() {}
} }
else if (entity.value().kind() == cpp_entity_kind::function_template_specialization_t) else if (entity.value().kind() == cpp_entity_kind::function_template_specialization_t)
{ {
auto& func = auto& func
static_cast<const cpp_function_template_specialization&>(entity.value()); = static_cast<const cpp_function_template_specialization&>(entity.value());
if (func.name() == "templ_c") if (func.name() == "templ_c")
{ {
REQUIRE(func.function().is_declaration()); REQUIRE(func.function().is_declaration());

View file

@ -270,8 +270,8 @@ using ns1::d;
)"; )";
cpp_entity_index idx; cpp_entity_index idx;
auto check_declaration = [&](const cpp_using_declaration& decl, const char* target_full_name, auto check_declaration
unsigned no) { = [&](const cpp_using_declaration& decl, const char* target_full_name, unsigned no) {
auto target = decl.target(); auto target = decl.target();
REQUIRE((target.no_overloaded() == no)); REQUIRE((target.no_overloaded() == no));
for (auto entity : target.get(idx)) for (auto entity : target.get(idx))

View file

@ -34,8 +34,8 @@ namespace ns2
)"; )";
const char* order[] = {"A", "B", "ns", "C", "D", "E", "ns2", "F"}; const char* order[] = {"A", "B", "ns", "C", "D", "E", "ns2", "F"};
auto check_macro = [](const cpp_macro_definition& macro, const char* replacement, auto check_macro
const char* args) { = [](const cpp_macro_definition& macro, const char* replacement, const char* args) {
REQUIRE(macro.replacement() == replacement); REQUIRE(macro.replacement() == replacement);
if (args) if (args)
{ {
@ -117,8 +117,8 @@ b
auto file_a = parse(idx, "header_a.hpp", header_a); auto file_a = parse(idx, "header_a.hpp", header_a);
auto file_b = parse(idx, "header_b.hpp", header_b); auto file_b = parse(idx, "header_b.hpp", header_b);
auto count = auto count
test_visit<cpp_include_directive>(*file_a, [&](const cpp_include_directive& include) { = test_visit<cpp_include_directive>(*file_a, [&](const cpp_include_directive& include) {
if (include.name() == "iostream") if (include.name() == "iostream")
{ {
REQUIRE(include.target().name() == include.name()); REQUIRE(include.target().name() == include.name());

View file

@ -45,8 +45,8 @@ using e = void;
{ {
REQUIRE(p.kind() == cpp_entity_kind::template_type_parameter_t); REQUIRE(p.kind() == cpp_entity_kind::template_type_parameter_t);
auto& param = auto& param
static_cast<const cpp_template_type_parameter&>(p); = static_cast<const cpp_template_type_parameter&>(p);
if (param.name() == "A") if (param.name() == "A")
{ {
REQUIRE(alias.name() == "a"); REQUIRE(alias.name() == "a");
@ -132,8 +132,8 @@ using d = void;
REQUIRE(p.kind() REQUIRE(p.kind()
== cpp_entity_kind::non_type_template_parameter_t); == cpp_entity_kind::non_type_template_parameter_t);
auto& param = auto& param
static_cast<const cpp_non_type_template_parameter&>(p); = static_cast<const cpp_non_type_template_parameter&>(p);
if (param.name() == "A") if (param.name() == "A")
{ {
REQUIRE(alias.name() == "a"); REQUIRE(alias.name() == "a");
@ -227,8 +227,8 @@ using d = void;
REQUIRE(p.kind() REQUIRE(p.kind()
== cpp_entity_kind::template_template_parameter_t); == cpp_entity_kind::template_template_parameter_t);
auto& param = auto& param
static_cast<const cpp_template_template_parameter&>(p); = static_cast<const cpp_template_template_parameter&>(p);
REQUIRE(param.keyword() == cpp_template_keyword::keyword_class); REQUIRE(param.keyword() == cpp_template_keyword::keyword_class);
if (param.name() == "A") if (param.name() == "A")
{ {

View file

@ -134,8 +134,8 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
case cpp_type_kind::template_parameter_t: case cpp_type_kind::template_parameter_t:
{ {
auto& entity_parsed = static_cast<const cpp_template_parameter_type&>(parsed).entity(); auto& entity_parsed = static_cast<const cpp_template_parameter_type&>(parsed).entity();
auto& entity_synthesized = auto& entity_synthesized
static_cast<const cpp_template_parameter_type&>(synthesized).entity(); = static_cast<const cpp_template_parameter_type&>(synthesized).entity();
return equal_ref(idx, entity_parsed, entity_synthesized); return equal_ref(idx, entity_parsed, entity_synthesized);
} }
case cpp_type_kind::template_instantiation_t: case cpp_type_kind::template_instantiation_t:
@ -357,8 +357,8 @@ typedef decltype(0) w;
} }
else if (alias.name() == "d") else if (alias.name() == "d")
{ {
auto type = auto type
cpp_pointer_type::build(add_cv(cpp_builtin_type::build(cpp_uint), cpp_cv_const)); = cpp_pointer_type::build(add_cv(cpp_builtin_type::build(cpp_uint), cpp_cv_const));
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));
} }
else if (alias.name() == "e") else if (alias.name() == "e")
@ -375,8 +375,8 @@ typedef decltype(0) w;
} }
else if (alias.name() == "g") else if (alias.name() == "g")
{ {
auto type = auto type
cpp_reference_type::build(add_cv(cpp_builtin_type::build(cpp_int), cpp_cv_const), = cpp_reference_type::build(add_cv(cpp_builtin_type::build(cpp_int), cpp_cv_const),
cpp_ref_rvalue); cpp_ref_rvalue);
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));
} }
@ -399,21 +399,21 @@ typedef decltype(0) w;
} }
else if (alias.name() == "k") else if (alias.name() == "k")
{ {
auto type = auto type
cpp_array_type::build(cpp_builtin_type::build(cpp_int), make_size("42", true)); = cpp_array_type::build(cpp_builtin_type::build(cpp_int), make_size("42", true));
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));
} }
else if (alias.name() == "l") else if (alias.name() == "l")
{ {
auto type = auto type
cpp_array_type::build(cpp_pointer_type::build(cpp_builtin_type::build(cpp_float)), = cpp_array_type::build(cpp_pointer_type::build(cpp_builtin_type::build(cpp_float)),
nullptr); nullptr);
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));
} }
else if (alias.name() == "m") else if (alias.name() == "m")
{ {
auto type = auto type
cpp_array_type::build(cpp_builtin_type::build(cpp_char), make_size("42", true)); = cpp_array_type::build(cpp_builtin_type::build(cpp_char), make_size("42", true));
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));
} }
else if (alias.name() == "n") else if (alias.name() == "n")
@ -474,10 +474,12 @@ typedef decltype(0) w;
} }
else if (alias.name() == "s") else if (alias.name() == "s")
{ {
auto pointee = cpp_member_object_type:: auto pointee
build(cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "foo")), = cpp_member_object_type::build(cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_unexposed_type::build( cpp_unexposed_type::build(
"int")); // type not exposed directly for some reason "int")); // type not exposed directly for some
// reason
auto type = cpp_pointer_type::build(std::move(pointee)); auto type = cpp_pointer_type::build(std::move(pointee));
REQUIRE(equal_types(idx, alias.underlying_type(), *type)); REQUIRE(equal_types(idx, alias.underlying_type(), *type));

View file

@ -16,53 +16,53 @@ TEST_CASE("stdlib", "[!hide][integration]")
//#include <cstdlib> -- problem with compiler built-in stuff on OSX //#include <cstdlib> -- problem with compiler built-in stuff on OSX
#include <csignal> #include <csignal>
//#include <csetjmp> -- same as above //#include <csetjmp> -- same as above
#include <cstdarg>
#include <typeinfo>
#include <typeindex>
#include <type_traits>
#include <bitset> #include <bitset>
#include <functional>
#include <utility>
#include <ctime>
#include <chrono> #include <chrono>
#include <cstdarg>
#include <cstddef> #include <cstddef>
#include <ctime>
#include <functional>
#include <initializer_list> #include <initializer_list>
#include <tuple> #include <tuple>
#include <type_traits>
#include <typeindex>
#include <typeinfo>
#include <utility>
#include <new>
#include <memory> #include <memory>
#include <new>
#include <scoped_allocator> #include <scoped_allocator>
#include <climits>
#include <cfloat> #include <cfloat>
#include <climits>
#include <cstdint> #include <cstdint>
//#include <cinttypes> -- missing types from C header (for some reason) //#include <cinttypes> -- missing types from C header (for some reason)
#include <limits> #include <limits>
//#include <exception> -- weird issue with compiler built-in stuff //#include <exception> -- weird issue with compiler built-in stuff
#include <stdexcept>
#include <cassert> #include <cassert>
#include <system_error>
#include <cerrno> #include <cerrno>
#include <stdexcept>
#include <system_error>
#include <cctype> #include <cctype>
#include <cwctype>
#include <cstring> #include <cstring>
#include <cwchar> #include <cwchar>
#include <cwctype>
//#include <cuchar> -- not supported on CI //#include <cuchar> -- not supported on CI
#include <string> #include <string>
#include <array> #include <array>
#include <vector>
#include <deque> #include <deque>
#include <list>
#include <forward_list> #include <forward_list>
#include <set> #include <list>
#include <map> #include <map>
#include <unordered_set>
#include <unordered_map>
#include <stack>
#include <queue> #include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <algorithm> #include <algorithm>
@ -70,22 +70,22 @@ TEST_CASE("stdlib", "[!hide][integration]")
//#include <cmath> -- non-conforming GCC extension with regards to constexpr //#include <cmath> -- non-conforming GCC extension with regards to constexpr
//#include <complex> -- weird double include issue under MSVC //#include <complex> -- weird double include issue under MSVC
#include <valarray>
#include <random>
#include <numeric> #include <numeric>
#include <random>
#include <ratio> #include <ratio>
#include <valarray>
//#include <cfenv> -- same issue with cinttypes //#include <cfenv> -- same issue with cinttypes
#include <iosfwd> #include <cstdio>
#include <fstream>
#include <iomanip>
#include <ios> #include <ios>
#include <iosfwd>
#include <iostream>
#include <istream> #include <istream>
#include <ostream> #include <ostream>
#include <iostream>
#include <fstream>
#include <sstream> #include <sstream>
#include <iomanip>
#include <streambuf> #include <streambuf>
#include <cstdio>
#include <locale> #include <locale>
//#include <clocale> -- issue on OSX //#include <clocale> -- issue on OSX
@ -94,10 +94,10 @@ TEST_CASE("stdlib", "[!hide][integration]")
//#include <atomic> -- issue on MSVC //#include <atomic> -- issue on MSVC
#include <thread>
#include <mutex>
#include <future>
#include <condition_variable> #include <condition_variable>
#include <future>
#include <mutex>
#include <thread>
)"; )";
write_file("stdlib.cpp", code); write_file("stdlib.cpp", code);

View file

@ -57,7 +57,7 @@ TEST_CASE("libclang_compile_config")
} }
])"; ])";
#define CPPAST_DETAIL_DRIVE "C:" # define CPPAST_DETAIL_DRIVE "C:"
#else #else
auto json = R"([ auto json = R"([
@ -83,7 +83,7 @@ TEST_CASE("libclang_compile_config")
} }
])"; ])";
#define CPPAST_DETAIL_DRIVE # define CPPAST_DETAIL_DRIVE
#endif #endif

View file

@ -65,7 +65,8 @@ TEST_CASE("preprocessing use external macro")
auto result = NAN; auto result = NAN;
#endif #endif
)", fast_preprocessing); )",
fast_preprocessing);
test_visit<cpp_variable>(*file, [&](const cpp_variable&) {}); test_visit<cpp_variable>(*file, [&](const cpp_variable&) {});
} }
@ -302,7 +303,8 @@ void j();
{ {
if (comment.content == "cstddef\ncstddef") if (comment.content == "cstddef\ncstddef")
// happens if include parsing is not supported // happens if include parsing is not supported
// error is still going to be detected because if it is supported, the entity will be matched above // error is still going to be detected because if it is supported, the entity will be
// matched above
add = 1u; add = 1u;
else else
REQUIRE(comment.content == "u"); REQUIRE(comment.content == "u");

View file

@ -6,12 +6,12 @@
#include <cxxopts.hpp> #include <cxxopts.hpp>
#include <cppast/libclang_parser.hpp> // for libclang_parser, libclang_compile_config, cpp_entity,...
#include <cppast/visitor.hpp> // for visit()
#include <cppast/code_generator.hpp> // for generate_code() #include <cppast/code_generator.hpp> // for generate_code()
#include <cppast/cpp_entity_kind.hpp> // for the cpp_entity_kind definition #include <cppast/cpp_entity_kind.hpp> // for the cpp_entity_kind definition
#include <cppast/cpp_forward_declarable.hpp> // for is_definition() #include <cppast/cpp_forward_declarable.hpp> // for is_definition()
#include <cppast/cpp_namespace.hpp> // for cpp_namespace #include <cppast/cpp_namespace.hpp> // for cpp_namespace
#include <cppast/libclang_parser.hpp> // for libclang_parser, libclang_compile_config, cpp_entity,...
#include <cppast/visitor.hpp> // for visit()
// print help options // print help options
void print_help(const cxxopts::Options& options) void print_help(const cxxopts::Options& options)
@ -239,12 +239,12 @@ int main(int argc, char* argv[]) try
cppast::libclang_compilation_database database( cppast::libclang_compilation_database database(
options["database_dir"].as<std::string>()); options["database_dir"].as<std::string>());
if (options.count("database_file")) if (options.count("database_file"))
config = config
cppast::libclang_compile_config(database, = cppast::libclang_compile_config(database,
options["database_file"].as<std::string>()); options["database_file"].as<std::string>());
else else
config = config
cppast::libclang_compile_config(database, options["file"].as<std::string>()); = cppast::libclang_compile_config(database, options["file"].as<std::string>());
} }
if (options.count("verbose")) if (options.count("verbose"))