Parse cpp_function_template
This commit is contained in:
parent
d6f0997fb6
commit
eeb48f1df5
18 changed files with 397 additions and 60 deletions
|
|
@ -4,12 +4,17 @@
|
|||
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
|
||||
#include <cppast/cpp_entity_kind.hpp>
|
||||
|
||||
using namespace cppast;
|
||||
|
||||
std::string cppast::full_name(const cpp_entity& e)
|
||||
{
|
||||
if (e.name().empty())
|
||||
return "";
|
||||
else if (is_parameter(e.kind()))
|
||||
// parameters don't have a full name
|
||||
return e.name();
|
||||
|
||||
std::string scopes;
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,95 @@ bool cppast::is_type(cpp_entity_kind kind) noexcept
|
|||
return false;
|
||||
}
|
||||
|
||||
bool cppast::is_function(cpp_entity_kind kind) noexcept
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case cpp_entity_kind::function_t:
|
||||
case cpp_entity_kind::member_function_t:
|
||||
case cpp_entity_kind::conversion_op_t:
|
||||
case cpp_entity_kind::constructor_t:
|
||||
case cpp_entity_kind::destructor_t:
|
||||
return true;
|
||||
|
||||
case cpp_entity_kind::file_t:
|
||||
case cpp_entity_kind::macro_definition_t:
|
||||
case cpp_entity_kind::include_directive_t:
|
||||
case cpp_entity_kind::language_linkage_t:
|
||||
case cpp_entity_kind::namespace_t:
|
||||
case cpp_entity_kind::namespace_alias_t:
|
||||
case cpp_entity_kind::using_directive_t:
|
||||
case cpp_entity_kind::using_declaration_t:
|
||||
case cpp_entity_kind::type_alias_t:
|
||||
case cpp_entity_kind::enum_t:
|
||||
case cpp_entity_kind::enum_value_t:
|
||||
case cpp_entity_kind::class_t:
|
||||
case cpp_entity_kind::access_specifier_t:
|
||||
case cpp_entity_kind::base_class_t:
|
||||
case cpp_entity_kind::variable_t:
|
||||
case cpp_entity_kind::member_variable_t:
|
||||
case cpp_entity_kind::bitfield_t:
|
||||
case cpp_entity_kind::function_parameter_t:
|
||||
case cpp_entity_kind::template_type_parameter_t:
|
||||
case cpp_entity_kind::non_type_template_parameter_t:
|
||||
case cpp_entity_kind::template_template_parameter_t:
|
||||
case cpp_entity_kind::alias_template_t:
|
||||
case cpp_entity_kind::variable_template_t:
|
||||
case cpp_entity_kind::function_template_t:
|
||||
case cpp_entity_kind::function_template_specialization_t:
|
||||
case cpp_entity_kind::class_template_t:
|
||||
case cpp_entity_kind::class_template_specialization_t:
|
||||
case cpp_entity_kind::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cppast::is_parameter(cpp_entity_kind kind) noexcept
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case cpp_entity_kind::function_parameter_t:
|
||||
case cpp_entity_kind::template_type_parameter_t:
|
||||
case cpp_entity_kind::non_type_template_parameter_t:
|
||||
case cpp_entity_kind::template_template_parameter_t:
|
||||
return true;
|
||||
|
||||
case cpp_entity_kind::file_t:
|
||||
case cpp_entity_kind::macro_definition_t:
|
||||
case cpp_entity_kind::include_directive_t:
|
||||
case cpp_entity_kind::language_linkage_t:
|
||||
case cpp_entity_kind::namespace_t:
|
||||
case cpp_entity_kind::namespace_alias_t:
|
||||
case cpp_entity_kind::using_directive_t:
|
||||
case cpp_entity_kind::using_declaration_t:
|
||||
case cpp_entity_kind::type_alias_t:
|
||||
case cpp_entity_kind::enum_t:
|
||||
case cpp_entity_kind::enum_value_t:
|
||||
case cpp_entity_kind::class_t:
|
||||
case cpp_entity_kind::access_specifier_t:
|
||||
case cpp_entity_kind::base_class_t:
|
||||
case cpp_entity_kind::variable_t:
|
||||
case cpp_entity_kind::member_variable_t:
|
||||
case cpp_entity_kind::bitfield_t:
|
||||
case cpp_entity_kind::function_t:
|
||||
case cpp_entity_kind::member_function_t:
|
||||
case cpp_entity_kind::conversion_op_t:
|
||||
case cpp_entity_kind::constructor_t:
|
||||
case cpp_entity_kind::destructor_t:
|
||||
case cpp_entity_kind::alias_template_t:
|
||||
case cpp_entity_kind::variable_template_t:
|
||||
case cpp_entity_kind::function_template_t:
|
||||
case cpp_entity_kind::function_template_specialization_t:
|
||||
case cpp_entity_kind::class_template_t:
|
||||
case cpp_entity_kind::class_template_specialization_t:
|
||||
case cpp_entity_kind::count:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cppast::is_template(cpp_entity_kind kind) noexcept
|
||||
{
|
||||
switch (kind)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,16 @@
|
|||
|
||||
using namespace cppast;
|
||||
|
||||
cpp_entity_kind cpp_function_template::do_get_entity_kind() const noexcept
|
||||
cpp_entity_kind cpp_function_template::kind() noexcept
|
||||
{
|
||||
return cpp_entity_kind::function_template_t;
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_function_template::do_get_entity_kind() const noexcept
|
||||
{
|
||||
return kind();
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_function_template_specialization::do_get_entity_kind() const noexcept
|
||||
{
|
||||
return cpp_entity_kind::function_template_specialization_t;
|
||||
|
|
|
|||
|
|
@ -57,17 +57,27 @@ std::unique_ptr<cpp_non_type_template_parameter> cpp_non_type_template_parameter
|
|||
return result;
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_non_type_template_parameter::do_get_entity_kind() const noexcept
|
||||
cpp_entity_kind cpp_non_type_template_parameter::kind() noexcept
|
||||
{
|
||||
return cpp_entity_kind::non_type_template_parameter_t;
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_non_type_template_parameter::do_get_entity_kind() const noexcept
|
||||
{
|
||||
return kind();
|
||||
}
|
||||
|
||||
bool detail::cpp_template_ref_predicate::operator()(const cpp_entity& e)
|
||||
{
|
||||
return is_template(e.kind()) || e.kind() == cpp_entity_kind::template_template_parameter_t;
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_template_template_parameter::do_get_entity_kind() const noexcept
|
||||
cpp_entity_kind cpp_template_template_parameter::kind() noexcept
|
||||
{
|
||||
return cpp_entity_kind::template_template_parameter_t;
|
||||
}
|
||||
|
||||
cpp_entity_kind cpp_template_template_parameter::do_get_entity_kind() const noexcept
|
||||
{
|
||||
return kind();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ namespace
|
|||
|
||||
std::unique_ptr<cpp_expression> default_value;
|
||||
detail::visit_children(cur, [&](const CXCursor& child) {
|
||||
DEBUG_ASSERT(clang_isExpression(child.kind) && !default_value,
|
||||
detail::parse_error_handler{}, child,
|
||||
if (!clang_isExpression(clang_getCursorKind(child)))
|
||||
return;
|
||||
|
||||
DEBUG_ASSERT(!default_value, detail::parse_error_handler{}, child,
|
||||
"unexpected child cursor of function parameter");
|
||||
default_value = detail::parse_expression(context, child);
|
||||
});
|
||||
|
|
@ -281,6 +283,7 @@ namespace
|
|||
detail::parse_type(context, cur,
|
||||
clang_getCursorResultType(cur)));
|
||||
context.comments.match(builder.get(), cur);
|
||||
|
||||
add_parameters(context, builder, cur);
|
||||
if (clang_Cursor_isVariadic(cur))
|
||||
builder.is_variadic();
|
||||
|
|
@ -301,21 +304,28 @@ namespace
|
|||
if (suffix.noexcept_condition)
|
||||
builder.noexcept_condition(std::move(suffix.noexcept_condition));
|
||||
|
||||
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind);
|
||||
if (clang_getTemplateCursorKind(cur) == CXCursor_NoDeclFound)
|
||||
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind);
|
||||
else
|
||||
return builder.finish(suffix.body_kind);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_entity> detail::parse_cpp_function(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_FunctionDecl, detail::assert_handler{});
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_FunctionDecl
|
||||
|| clang_getTemplateCursorKind(cur) == CXCursor_FunctionDecl,
|
||||
detail::assert_handler{});
|
||||
return parse_cpp_function_impl(context, cur);
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_entity> detail::try_parse_static_cpp_function(
|
||||
const detail::parse_context& context, const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_CXXMethod, detail::assert_handler{});
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_CXXMethod
|
||||
|| clang_getTemplateCursorKind(cur) == CXCursor_CXXMethod,
|
||||
detail::assert_handler{});
|
||||
if (clang_CXXMethod_isStatic(cur))
|
||||
return parse_cpp_function_impl(context, cur);
|
||||
return nullptr;
|
||||
|
|
@ -410,7 +420,9 @@ namespace
|
|||
std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_CXXMethod, detail::assert_handler{});
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_CXXMethod
|
||||
|| clang_getTemplateCursorKind(cur) == CXCursor_CXXMethod,
|
||||
detail::assert_handler{});
|
||||
auto name = detail::get_cursor_name(cur);
|
||||
|
||||
cpp_member_function::builder builder(name.c_str(),
|
||||
|
|
@ -435,9 +447,14 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::pars
|
|||
std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_ConversionFunction, detail::assert_handler{});
|
||||
cpp_conversion_op::builder builder(
|
||||
detail::parse_type(context, cur, clang_getCursorResultType(cur)));
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_ConversionFunction
|
||||
|| clang_getTemplateCursorKind(cur) == CXCursor_ConversionFunction,
|
||||
detail::assert_handler{});
|
||||
|
||||
auto type = clang_getCursorResultType(cur);
|
||||
cpp_conversion_op::builder builder(std::string("operator ")
|
||||
+ cxstring(clang_getTypeSpelling(type)).c_str(),
|
||||
detail::parse_type(context, cur, type));
|
||||
context.comments.match(builder.get(), cur);
|
||||
|
||||
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||
|
|
@ -455,7 +472,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
|
|||
else if (detail::skip_if(stream, "explicit"))
|
||||
builder.is_explicit();
|
||||
else
|
||||
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected token");
|
||||
stream.bump();
|
||||
}
|
||||
|
||||
// heuristic to find arguments tokens
|
||||
|
|
@ -485,7 +502,9 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
|
|||
std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_Constructor, detail::assert_handler{});
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_Constructor
|
||||
|| clang_getTemplateCursorKind(cur) == CXCursor_Constructor,
|
||||
detail::assert_handler{});
|
||||
auto name = detail::get_cursor_name(cur);
|
||||
|
||||
cpp_constructor::builder builder(name.c_str());
|
||||
|
|
@ -505,7 +524,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
|
|||
else if (detail::skip_if(stream, "explicit"))
|
||||
builder.is_explicit();
|
||||
else
|
||||
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected token");
|
||||
stream.bump();
|
||||
}
|
||||
|
||||
skip_parameters(stream);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ detail::cxstring detail::get_cursor_name(const CXCursor& cur)
|
|||
|
||||
cpp_storage_class_specifiers detail::get_storage_class(const CXCursor& cur)
|
||||
{
|
||||
if (clang_getTemplateCursorKind(cur) != CXCursor_NoDeclFound)
|
||||
return cpp_storage_class_none;
|
||||
|
||||
switch (clang_Cursor_getStorageClass(cur))
|
||||
{
|
||||
case CX_SC_Invalid:
|
||||
|
|
@ -42,11 +45,11 @@ cpp_storage_class_specifiers detail::get_storage_class(const CXCursor& cur)
|
|||
case CX_SC_PrivateExtern:
|
||||
case CX_SC_OpenCLWorkGroupLocal:
|
||||
// non-exposed storage classes
|
||||
return cpp_storage_class_auto;
|
||||
return cpp_storage_class_none;
|
||||
}
|
||||
|
||||
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected storage class");
|
||||
return cpp_storage_class_auto;
|
||||
return cpp_storage_class_none;
|
||||
}
|
||||
|
||||
void detail::comment_context::match(cpp_entity& e, const CXCursor& cur) const
|
||||
|
|
@ -120,6 +123,8 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
|||
|
||||
case CXCursor_TypeAliasTemplateDecl:
|
||||
return parse_cpp_alias_template(context, cur);
|
||||
case CXCursor_FunctionTemplate:
|
||||
return parse_cpp_function_template(context, cur);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ namespace cppast
|
|||
|
||||
std::unique_ptr<cpp_entity> parse_cpp_alias_template(const parse_context& context,
|
||||
const CXCursor& cur);
|
||||
std::unique_ptr<cpp_entity> parse_cpp_function_template(const parse_context& context,
|
||||
const CXCursor& cur);
|
||||
|
||||
// as_template: true, iff currently parsing a template
|
||||
std::unique_ptr<cpp_entity> parse_entity(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
// found in the top-level directory of this distribution.
|
||||
|
||||
#include <cppast/cpp_alias_template.hpp>
|
||||
#include <cppast/cpp_function_template.hpp>
|
||||
|
||||
#include <cppast/cpp_entity_kind.hpp>
|
||||
|
||||
#include "libclang_visitor.hpp"
|
||||
#include "parse_functions.hpp"
|
||||
|
|
@ -11,9 +14,9 @@ using namespace cppast;
|
|||
|
||||
namespace
|
||||
{
|
||||
template <typename TemplateT, typename EntityT>
|
||||
template <typename TemplateT, typename EntityT, typename Predicate>
|
||||
type_safe::optional<typename TemplateT::builder> get_builder(
|
||||
const detail::parse_context& context, const CXCursor& cur)
|
||||
const detail::parse_context& context, const CXCursor& cur, Predicate p)
|
||||
{
|
||||
// we need the actual entity first, then the parameters
|
||||
// so two visit calls are required
|
||||
|
|
@ -34,7 +37,7 @@ namespace
|
|||
auto entity = detail::parse_entity(context, result, cur);
|
||||
if (!entity)
|
||||
return type_safe::nullopt;
|
||||
DEBUG_ASSERT(entity->kind() == EntityT::kind(), detail::parse_error_handler{}, cur,
|
||||
DEBUG_ASSERT(p(entity->kind()), detail::parse_error_handler{}, cur,
|
||||
"wrong child of template");
|
||||
return typename TemplateT::builder(
|
||||
std::unique_ptr<EntityT>(static_cast<EntityT*>(entity.release())));
|
||||
|
|
@ -206,10 +209,55 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_alias_template(const detail::parse
|
|||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_TypeAliasTemplateDecl,
|
||||
detail::assert_handler{});
|
||||
auto builder = get_builder<cpp_alias_template, cpp_type_alias>(context, cur);
|
||||
auto builder =
|
||||
get_builder<cpp_alias_template, cpp_type_alias>(context, cur, [](cpp_entity_kind k) {
|
||||
return k == cpp_entity_kind::type_alias_t;
|
||||
});
|
||||
if (!builder)
|
||||
return nullptr;
|
||||
context.comments.match(builder.value().get(), cur);
|
||||
parse_parameters(builder.value(), context, cur);
|
||||
return builder.value().finish(*context.idx, detail::get_entity_id(cur));
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_entity> detail::parse_cpp_function_template(
|
||||
const detail::parse_context& context, const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_FunctionTemplate, detail::assert_handler{});
|
||||
|
||||
std::unique_ptr<cpp_entity> func;
|
||||
switch (clang_getTemplateCursorKind(cur))
|
||||
{
|
||||
case CXCursor_FunctionDecl:
|
||||
func = detail::parse_cpp_function(context, cur);
|
||||
break;
|
||||
case CXCursor_CXXMethod:
|
||||
if (auto sfunc = detail::try_parse_static_cpp_function(context, cur))
|
||||
func = std::move(sfunc);
|
||||
else
|
||||
func = detail::parse_cpp_member_function(context, cur);
|
||||
break;
|
||||
case CXCursor_ConversionFunction:
|
||||
func = detail::parse_cpp_conversion_op(context, cur);
|
||||
break;
|
||||
case CXCursor_Constructor:
|
||||
func = detail::parse_cpp_constructor(context, cur);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected template cursor kind");
|
||||
}
|
||||
|
||||
if (!func)
|
||||
return nullptr;
|
||||
|
||||
// steal comment
|
||||
auto comment = type_safe::copy(func->comment());
|
||||
func->set_comment(type_safe::nullopt);
|
||||
|
||||
cpp_function_template::builder builder(
|
||||
std::unique_ptr<cpp_function_base>(static_cast<cpp_function_base*>(func.release())));
|
||||
builder.get().set_comment(std::move(comment));
|
||||
parse_parameters(builder, context, cur);
|
||||
return builder.finish(*context.idx, detail::get_entity_id(cur));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue