Parse cpp_class_template_specialization

This commit is contained in:
Jonathan Müller 2017-03-27 11:51:30 +02:00
commit 1bbc962b8c
7 changed files with 120 additions and 6 deletions

View file

@ -44,14 +44,13 @@ namespace cppast
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;
/// Builder for [cppast::cpp_class_template_specialization](). /// Builder for [cppast::cpp_class_template_specialization]().
class builder : public specialization_builder<cpp_class_template_specialization, cpp_class> class builder : public specialization_builder<cpp_class_template_specialization, cpp_class>
{ {
public: public:
using specialization_builder::specialization_builder; using specialization_builder::specialization_builder;
private:
using specialization_builder::add_parameter;
}; };
/// A reference to the class that is being specialized. /// A reference to the class that is being specialized.

View file

@ -18,7 +18,12 @@ cpp_entity_kind cpp_class_template::do_get_entity_kind() const noexcept
return kind(); return kind();
} }
cpp_entity_kind cpp_class_template_specialization::do_get_entity_kind() const noexcept cpp_entity_kind cpp_class_template_specialization::kind() noexcept
{ {
return cpp_entity_kind::class_template_specialization_t; return cpp_entity_kind::class_template_specialization_t;
} }
cpp_entity_kind cpp_class_template_specialization::do_get_entity_kind() const noexcept
{
return kind();
}

View file

@ -104,12 +104,15 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
else if (kind == CXCursor_CXXFinalAttr) else if (kind == CXCursor_CXXFinalAttr)
builder.is_final(); builder.is_final();
else if (kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter else if (kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter
|| kind == CXCursor_TemplateTemplateParameter) || kind == CXCursor_TemplateTemplateParameter || clang_isExpression(kind)
|| clang_isReference(kind))
// other children due to templates and stuff
return; return;
else if (auto entity = parse_entity(context, child)) else if (auto entity = parse_entity(context, child))
builder.add_child(std::move(entity)); builder.add_child(std::move(entity));
}); });
auto is_templated = clang_getTemplateCursorKind(cur) != CXCursor_NoDeclFound; auto is_templated = (clang_getTemplateCursorKind(cur) != CXCursor_NoDeclFound
|| !clang_Cursor_isNull(clang_getSpecializedCursorTemplate(cur)));
if (clang_isCursorDefinition(cur)) if (clang_isCursorDefinition(cur))
return is_templated ? builder.finish() : builder.finish(*context.idx, get_entity_id(cur)); return is_templated ? builder.finish() : builder.finish(*context.idx, get_entity_id(cur));
else else

View file

@ -100,6 +100,8 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
case CXCursor_ClassDecl: case CXCursor_ClassDecl:
case CXCursor_StructDecl: case CXCursor_StructDecl:
case CXCursor_UnionDecl: case CXCursor_UnionDecl:
if (auto spec = try_parse_full_cpp_class_template_specialization(context, cur))
return spec;
return parse_cpp_class(context, cur); return parse_cpp_class(context, cur);
case CXCursor_VarDecl: case CXCursor_VarDecl:
@ -134,6 +136,8 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
return parse_cpp_function_template(context, cur); return parse_cpp_function_template(context, cur);
case CXCursor_ClassTemplate: case CXCursor_ClassTemplate:
return parse_cpp_class_template(context, cur); return parse_cpp_class_template(context, cur);
case CXCursor_ClassTemplatePartialSpecialization:
return parse_cpp_class_template_specialization(context, cur);
default: default:
break; break;

View file

@ -95,6 +95,10 @@ namespace cppast
std::unique_ptr<cpp_entity> try_parse_cpp_function_template_specialization( std::unique_ptr<cpp_entity> try_parse_cpp_function_template_specialization(
const parse_context& context, const CXCursor& cur); const parse_context& context, const CXCursor& cur);
// on class cursors
std::unique_ptr<cpp_entity> try_parse_full_cpp_class_template_specialization(
const parse_context& context, const CXCursor& cur);
std::unique_ptr<cpp_entity> parse_cpp_namespace(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_namespace(const parse_context& context,
const CXCursor& cur); const CXCursor& cur);
std::unique_ptr<cpp_entity> parse_cpp_namespace_alias(const parse_context& context, std::unique_ptr<cpp_entity> parse_cpp_namespace_alias(const parse_context& context,
@ -135,6 +139,8 @@ namespace cppast
const CXCursor& cur); const CXCursor& cur);
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(
const parse_context& context, const CXCursor& cur);
// as_template: true, iff currently parsing a template // as_template: true, iff currently parsing a template
std::unique_ptr<cpp_entity> parse_entity( std::unique_ptr<cpp_entity> parse_entity(

View file

@ -355,3 +355,45 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class_template(const detail::parse
return builder.finish(*context.idx, detail::get_entity_id(cur), return builder.finish(*context.idx, detail::get_entity_id(cur),
builder.get().class_().is_definition()); builder.get().class_().is_definition());
} }
std::unique_ptr<cpp_entity> detail::try_parse_full_cpp_class_template_specialization(
const detail::parse_context& context, const CXCursor& cur)
{
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_ClassDecl
|| clang_getCursorKind(cur) == CXCursor_StructDecl
|| clang_getCursorKind(cur) == CXCursor_UnionDecl,
detail::assert_handler{});
auto templ = clang_getSpecializedCursorTemplate(cur);
if (clang_Cursor_isNull(templ))
return nullptr;
return detail::parse_cpp_class_template_specialization(context, cur);
}
std::unique_ptr<cpp_entity> detail::parse_cpp_class_template_specialization(
const detail::parse_context& context, const CXCursor& cur)
{
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_ClassTemplatePartialSpecialization
|| clang_getCursorKind(cur) == CXCursor_ClassDecl
|| clang_getCursorKind(cur) == CXCursor_StructDecl
|| clang_getCursorKind(cur) == CXCursor_UnionDecl,
detail::assert_handler{});
auto primary = clang_getSpecializedCursorTemplate(cur);
auto c = detail::parse_cpp_class(context, cur);
if (!c)
return nullptr;
// steal comment
auto comment = type_safe::copy(c->comment());
c->set_comment(type_safe::nullopt);
cpp_class_template_specialization::builder
builder(std::unique_ptr<cpp_class>(static_cast<cpp_class*>(c.release())),
cpp_template_ref(detail::get_entity_id(primary), ""));
builder.get().set_comment(std::move(comment));
parse_parameters(builder, context, cur);
parse_arguments(builder, context, cur);
return builder.finish(*context.idx, detail::get_entity_id(cur),
builder.get().class_().is_definition());
}

View file

@ -41,6 +41,20 @@ struct e
template <typename U> template <typename U>
T func(U); T func(U);
}; };
// full specialization
template <>
class a<int> {};
template <>
struct b<0, int> {};
// partial specialization
template <typename T>
class a<T*> {};
template <typename T>
struct b<0, T> {};
)"; )";
cpp_entity_index idx; cpp_entity_index idx;
@ -168,4 +182,45 @@ struct e
} }
}); });
REQUIRE(count == 5u); REQUIRE(count == 5u);
count = test_visit<cpp_class_template_specialization>(
*file, [&](const cpp_class_template_specialization& templ) {
REQUIRE(!templ.arguments_exposed());
if (templ.name() == "a")
{
REQUIRE(equal_ref(idx, templ.primary_template(),
cpp_template_ref(cpp_entity_id(""), "a")));
if (templ.is_full_specialization())
{
check_template_parameters(templ, {});
REQUIRE(templ.unexposed_arguments() == "int");
}
else
{
check_template_parameters(templ,
{{cpp_entity_kind::template_type_parameter_t, "T"}});
REQUIRE(templ.unexposed_arguments() == "T*");
}
}
else if (templ.name() == "b")
{
REQUIRE(equal_ref(idx, templ.primary_template(),
cpp_template_ref(cpp_entity_id(""), "b")));
if (templ.is_full_specialization())
{
check_template_parameters(templ, {});
REQUIRE(templ.unexposed_arguments() == "0,int");
}
else
{
check_template_parameters(templ,
{{cpp_entity_kind::template_type_parameter_t, "T"}});
REQUIRE(templ.unexposed_arguments() == "0,T");
}
}
else
REQUIRE(false);
});
REQUIRE(count == 4u);
} }