Parse cpp_class_template_specialization
This commit is contained in:
parent
22fd582756
commit
1bbc962b8c
7 changed files with 120 additions and 6 deletions
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue