Parse cpp_destructor
This commit is contained in:
parent
68c74a9f07
commit
e787b845d5
6 changed files with 118 additions and 5 deletions
|
|
@ -294,6 +294,8 @@ namespace cppast
|
||||||
class cpp_destructor final : public cpp_function_base
|
class cpp_destructor final : public cpp_function_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static cpp_entity_kind kind() noexcept;
|
||||||
|
|
||||||
/// Builds a [cppast::cpp_destructor]().
|
/// Builds a [cppast::cpp_destructor]().
|
||||||
class builder : public basic_builder<cpp_destructor>
|
class builder : public basic_builder<cpp_destructor>
|
||||||
{
|
{
|
||||||
|
|
@ -331,6 +333,8 @@ namespace cppast
|
||||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||||
|
|
||||||
cpp_virtual virtual_;
|
cpp_virtual virtual_;
|
||||||
|
|
||||||
|
friend basic_builder<cpp_destructor>;
|
||||||
};
|
};
|
||||||
} // namespace cppast
|
} // namespace cppast
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,12 @@ cpp_entity_kind cpp_constructor::do_get_entity_kind() const noexcept
|
||||||
return kind();
|
return kind();
|
||||||
}
|
}
|
||||||
|
|
||||||
cpp_entity_kind cpp_destructor::do_get_entity_kind() const noexcept
|
cpp_entity_kind cpp_destructor::kind() noexcept
|
||||||
{
|
{
|
||||||
return cpp_entity_kind::destructor_t;
|
return cpp_entity_kind::destructor_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpp_entity_kind cpp_destructor::do_get_entity_kind() const noexcept
|
||||||
|
{
|
||||||
|
return kind();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -373,13 +373,29 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Builder>
|
||||||
|
auto set_qualifier(int, Builder& b, cpp_cv cv, cpp_reference ref)
|
||||||
|
-> decltype(b.cv_ref_qualifier(cv, ref), true)
|
||||||
|
{
|
||||||
|
b.cv_ref_qualifier(cv, ref);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Builder>
|
||||||
|
bool set_qualifier(short, Builder&, cpp_cv, cpp_reference)
|
||||||
|
{
|
||||||
|
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, Builder& builder,
|
const CXCursor& cur, Builder& builder,
|
||||||
detail::token_stream& stream, bool is_virtual)
|
detail::token_stream& stream, bool is_virtual)
|
||||||
{
|
{
|
||||||
auto suffix = parse_suffix_info(stream, context, true, true);
|
auto allow_qualifiers = set_qualifier(0, builder, cpp_cv_none, cpp_ref_none);
|
||||||
builder.cv_ref_qualifier(suffix.cv_qualifier, suffix.ref_qualifier);
|
|
||||||
|
auto suffix = parse_suffix_info(stream, context, allow_qualifiers, true);
|
||||||
|
set_qualifier(0, builder, suffix.cv_qualifier, suffix.ref_qualifier);
|
||||||
if (suffix.noexcept_condition)
|
if (suffix.noexcept_condition)
|
||||||
builder.noexcept_condition(move(suffix.noexcept_condition));
|
builder.noexcept_condition(move(suffix.noexcept_condition));
|
||||||
if (auto virt = calculate_virtual(cur, is_virtual, suffix.virtual_keywords))
|
if (auto virt = calculate_virtual(cur, is_virtual, suffix.virtual_keywords))
|
||||||
|
|
@ -434,7 +450,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
|
||||||
else if (detail::skip_if(stream, "explicit"))
|
else if (detail::skip_if(stream, "explicit"))
|
||||||
builder.is_explicit();
|
builder.is_explicit();
|
||||||
else
|
else
|
||||||
stream.bump();
|
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected token");
|
||||||
}
|
}
|
||||||
|
|
||||||
// heuristic to find arguments tokens
|
// heuristic to find arguments tokens
|
||||||
|
|
@ -483,7 +499,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
|
||||||
else if (detail::skip_if(stream, "explicit"))
|
else if (detail::skip_if(stream, "explicit"))
|
||||||
builder.is_explicit();
|
builder.is_explicit();
|
||||||
else
|
else
|
||||||
stream.bump();
|
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected token");
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_parameters(stream);
|
skip_parameters(stream);
|
||||||
|
|
@ -494,3 +510,21 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
|
||||||
|
|
||||||
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::unique_ptr<cpp_entity> detail::parse_cpp_destructor(const detail::parse_context& context,
|
||||||
|
const CXCursor& cur)
|
||||||
|
{
|
||||||
|
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_Destructor, detail::assert_handler{});
|
||||||
|
|
||||||
|
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||||
|
detail::token_stream stream(tokenizer, cur);
|
||||||
|
|
||||||
|
auto is_virtual = detail::skip_if(stream, "virtual");
|
||||||
|
detail::skip(stream, "~");
|
||||||
|
auto name = std::string("~") + stream.get().c_str();
|
||||||
|
cpp_destructor::builder builder(std::move(name));
|
||||||
|
|
||||||
|
detail::skip(stream, "(");
|
||||||
|
detail::skip(stream, ")");
|
||||||
|
return handle_suffix(context, cur, builder, stream, is_virtual);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,8 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
||||||
return parse_cpp_conversion_op(context, cur);
|
return parse_cpp_conversion_op(context, cur);
|
||||||
case CXCursor_Constructor:
|
case CXCursor_Constructor:
|
||||||
return parse_cpp_constructor(context, cur);
|
return parse_cpp_constructor(context, cur);
|
||||||
|
case CXCursor_Destructor:
|
||||||
|
return parse_cpp_destructor(context, cur);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,8 @@ namespace cppast
|
||||||
const CXCursor& cur);
|
const CXCursor& cur);
|
||||||
std::unique_ptr<cpp_entity> parse_cpp_constructor(const parse_context& context,
|
std::unique_ptr<cpp_entity> parse_cpp_constructor(const parse_context& context,
|
||||||
const CXCursor& cur);
|
const CXCursor& cur);
|
||||||
|
std::unique_ptr<cpp_entity> parse_cpp_destructor(const parse_context& context,
|
||||||
|
const CXCursor& cur);
|
||||||
|
|
||||||
std::unique_ptr<cpp_entity> parse_entity(const parse_context& context, const CXCursor& cur);
|
std::unique_ptr<cpp_entity> parse_entity(const parse_context& context, const CXCursor& cur);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ struct foo
|
||||||
auto file = parse(idx, "cpp_constructor.cpp", code);
|
auto file = parse(idx, "cpp_constructor.cpp", code);
|
||||||
auto count = test_visit<cpp_constructor>(*file, [&](const cpp_constructor& cont) {
|
auto count = test_visit<cpp_constructor>(*file, [&](const cpp_constructor& cont) {
|
||||||
REQUIRE(!cont.is_variadic());
|
REQUIRE(!cont.is_variadic());
|
||||||
|
REQUIRE(cont.name() == "foo");
|
||||||
|
|
||||||
if (count_children(cont) == 0u)
|
if (count_children(cont) == 0u)
|
||||||
{
|
{
|
||||||
|
|
@ -233,3 +234,68 @@ struct foo
|
||||||
});
|
});
|
||||||
REQUIRE(count == 3u);
|
REQUIRE(count == 3u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("cpp_destructor")
|
||||||
|
{
|
||||||
|
auto code = R"(
|
||||||
|
struct a
|
||||||
|
{
|
||||||
|
~a();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct b
|
||||||
|
{
|
||||||
|
~b() noexcept(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct c
|
||||||
|
{
|
||||||
|
virtual ~c() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct d : c
|
||||||
|
{
|
||||||
|
~d() final;
|
||||||
|
};
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto file = parse({}, "cpp_destructor.cpp", code);
|
||||||
|
auto count = test_visit<cpp_destructor>(*file, [&](const cpp_destructor& dtor) {
|
||||||
|
REQUIRE(count_children(dtor) == 0u);
|
||||||
|
REQUIRE(!dtor.is_variadic());
|
||||||
|
|
||||||
|
if (dtor.name() == "~a")
|
||||||
|
{
|
||||||
|
REQUIRE(!dtor.is_virtual());
|
||||||
|
REQUIRE(dtor.is_declaration());
|
||||||
|
REQUIRE(!dtor.noexcept_condition());
|
||||||
|
}
|
||||||
|
else if (dtor.name() == "~b")
|
||||||
|
{
|
||||||
|
REQUIRE(!dtor.is_virtual());
|
||||||
|
REQUIRE(dtor.body_kind() == cpp_function_definition);
|
||||||
|
REQUIRE(dtor.noexcept_condition());
|
||||||
|
REQUIRE(
|
||||||
|
equal_expressions(dtor.noexcept_condition().value(),
|
||||||
|
*cpp_unexposed_expression::build(cpp_builtin_type::build("bool"),
|
||||||
|
"false")));
|
||||||
|
}
|
||||||
|
else if (dtor.name() == "~c")
|
||||||
|
{
|
||||||
|
REQUIRE(dtor.virtual_info());
|
||||||
|
REQUIRE(dtor.virtual_info().value() == type_safe::flag_set<cpp_virtual_flags>{});
|
||||||
|
REQUIRE(dtor.body_kind() == cpp_function_defaulted);
|
||||||
|
REQUIRE(!dtor.noexcept_condition());
|
||||||
|
}
|
||||||
|
else if (dtor.name() == "~d")
|
||||||
|
{
|
||||||
|
REQUIRE(dtor.virtual_info());
|
||||||
|
REQUIRE(dtor.virtual_info().value()
|
||||||
|
== (cpp_virtual_flags::override | cpp_virtual_flags::final));
|
||||||
|
REQUIRE(!dtor.noexcept_condition());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
REQUIRE(false);
|
||||||
|
});
|
||||||
|
REQUIRE(count == 4u);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue