Fix multidimensional array of incomplete size

Fixes #129.
This commit is contained in:
Jonathan Müller 2022-02-06 21:50:54 +01:00
commit 373717cc5e
2 changed files with 103 additions and 85 deletions

View file

@ -25,8 +25,7 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
return static_cast<const cpp_builtin_type&>(parsed).builtin_type_kind()
== static_cast<const cpp_builtin_type&>(synthesized).builtin_type_kind();
case cpp_type_kind::user_defined_t:
{
case cpp_type_kind::user_defined_t: {
auto& user_parsed = static_cast<const cpp_user_defined_type&>(parsed);
auto& user_synthesized = static_cast<const cpp_user_defined_type&>(synthesized);
return equal_ref(idx, user_parsed.entity(), user_synthesized.entity());
@ -40,8 +39,7 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
case cpp_type_kind::decltype_auto_t:
return true;
case cpp_type_kind::cv_qualified_t:
{
case cpp_type_kind::cv_qualified_t: {
auto& cv_a = static_cast<const cpp_cv_qualified_type&>(parsed);
auto& cv_b = static_cast<const cpp_cv_qualified_type&>(synthesized);
return cv_a.cv_qualifier() == cv_b.cv_qualifier()
@ -51,16 +49,14 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
case cpp_type_kind::pointer_t:
return equal_types(idx, static_cast<const cpp_pointer_type&>(parsed).pointee(),
static_cast<const cpp_pointer_type&>(synthesized).pointee());
case cpp_type_kind::reference_t:
{
case cpp_type_kind::reference_t: {
auto& ref_a = static_cast<const cpp_reference_type&>(parsed);
auto& ref_b = static_cast<const cpp_reference_type&>(synthesized);
return ref_a.reference_kind() == ref_b.reference_kind()
&& equal_types(idx, ref_a.referee(), ref_b.referee());
}
case cpp_type_kind::array_t:
{
case cpp_type_kind::array_t: {
auto& array_a = static_cast<const cpp_array_type&>(parsed);
auto& array_b = static_cast<const cpp_array_type&>(synthesized);
@ -71,14 +67,15 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
// check size
if (!array_a.size().has_value() && !array_b.size().has_value())
return true;
else if (array_a.size().has_value() != array_b.size().has_value())
return false;
auto& size_a = array_a.size().value();
auto& size_b = array_b.size().value();
return equal_expressions(size_a, size_b);
}
case cpp_type_kind::function_t:
{
case cpp_type_kind::function_t: {
auto& func_a = static_cast<const cpp_function_type&>(parsed);
auto& func_b = static_cast<const cpp_function_type&>(synthesized);
@ -98,8 +95,7 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
}
return iter_a == func_a.parameter_types().end() && iter_b == func_b.parameter_types().end();
}
case cpp_type_kind::member_function_t:
{
case cpp_type_kind::member_function_t: {
auto& func_a = static_cast<const cpp_member_function_type&>(parsed);
auto& func_b = static_cast<const cpp_member_function_type&>(synthesized);
@ -121,8 +117,7 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
}
return iter_a == func_a.parameter_types().end() && iter_b == func_b.parameter_types().end();
}
case cpp_type_kind::member_object_t:
{
case cpp_type_kind::member_object_t: {
auto& obj_a = static_cast<const cpp_member_object_type&>(parsed);
auto& obj_b = static_cast<const cpp_member_object_type&>(synthesized);
@ -131,15 +126,13 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
return equal_types(idx, obj_a.object_type(), obj_b.object_type());
}
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_synthesized
= static_cast<const cpp_template_parameter_type&>(synthesized).entity();
return equal_ref(idx, entity_parsed, entity_synthesized);
}
case cpp_type_kind::template_instantiation_t:
{
case cpp_type_kind::template_instantiation_t: {
auto& inst_parsed = static_cast<const cpp_template_instantiation_type&>(parsed);
auto& inst_synthesized = static_cast<const cpp_template_instantiation_type&>(synthesized);
@ -182,8 +175,7 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
return iter_a == inst_parsed.arguments().value().end()
&& iter_b == inst_synthesized.arguments().value().end();
}
case cpp_type_kind::dependent_t:
{
case cpp_type_kind::dependent_t: {
auto& dep_a = static_cast<const cpp_dependent_type&>(parsed);
auto& dep_b = static_cast<const cpp_dependent_type&>(synthesized);
return dep_a.name() == dep_b.name() && equal_types(idx, dep_a.dependee(), dep_b.dependee());
@ -242,6 +234,8 @@ using k = int[42];
using l = float*[];
/// using m=char[42];
using m = char[3 * 2 + 4 ? 42 : 43];
/// using m2=char[][1];
using m2 = char[][1];
// function pointers
/// using n=void(*)(int);
@ -299,6 +293,7 @@ typedef e* j;
typedef int k[42];
typedef float* l[];
typedef char m[3 * 2 + 4 ? 42 : 43];
typedef char m2[][1];
// function pointers
typedef void(*n)(int);
@ -343,78 +338,85 @@ typedef decltype(0) w;
if (alias.name() == "a")
{
auto type = cpp_builtin_type::build(cpp_int);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "b")
{
auto type = add_cv(cpp_builtin_type::build(cpp_longdouble), cpp_cv_const_volatile);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "c")
{
auto type = cpp_pointer_type::build(cpp_builtin_type::build(cpp_int));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "d")
{
auto type
= cpp_pointer_type::build(add_cv(cpp_builtin_type::build(cpp_uint), cpp_cv_const));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "e")
{
auto type = add_cv(cpp_pointer_type::build(
add_cv(cpp_builtin_type::build(cpp_uint), cpp_cv_const)),
cpp_cv_volatile);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
add_cv(cpp_builtin_type::build(cpp_uint), cpp_cv_const)),
cpp_cv_volatile);
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "f")
{
auto type = cpp_reference_type::build(cpp_builtin_type::build(cpp_int), cpp_ref_lvalue);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "g")
{
auto type
= cpp_reference_type::build(add_cv(cpp_builtin_type::build(cpp_int), cpp_cv_const),
cpp_ref_rvalue);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
cpp_ref_rvalue);
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "h")
{
auto type = cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "c"));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "i")
{
auto type = add_cv(cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "d")),
cpp_cv_const);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
cpp_cv_const);
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "j")
{
auto type = cpp_pointer_type::build(
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "e")));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "e")));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "k")
{
auto type
= cpp_array_type::build(cpp_builtin_type::build(cpp_int), make_size("42", true));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "l")
{
auto type
= cpp_array_type::build(cpp_pointer_type::build(cpp_builtin_type::build(cpp_float)),
nullptr);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
nullptr);
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "m")
{
auto type
= cpp_array_type::build(cpp_builtin_type::build(cpp_char), make_size("42", true));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "m2")
{
auto inner
= cpp_array_type::build(cpp_builtin_type::build(cpp_char), make_size("1", true));
auto type = cpp_array_type::build(std::move(inner), nullptr);
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "n")
{
@ -422,108 +424,108 @@ typedef decltype(0) w;
builder.add_parameter(cpp_builtin_type::build(cpp_int));
auto type = cpp_pointer_type::build(builder.finish());
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "o")
{
cpp_function_type::builder builder(
cpp_pointer_type::build(cpp_builtin_type::build(cpp_char)));
cpp_pointer_type::build(cpp_builtin_type::build(cpp_char)));
builder.add_parameter(
cpp_reference_type::build(add_cv(cpp_builtin_type::build(cpp_int), cpp_cv_const),
cpp_ref_lvalue));
cpp_reference_type::build(add_cv(cpp_builtin_type::build(cpp_int), cpp_cv_const),
cpp_ref_lvalue));
builder.is_variadic();
auto type = cpp_reference_type::build(builder.finish(), cpp_ref_lvalue);
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "p")
{
cpp_function_type::builder builder(
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "n")));
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "n")));
builder.add_parameter(cpp_builtin_type::build(cpp_int));
builder.add_parameter(
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "o")));
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "o")));
auto type = cpp_pointer_type::build(builder.finish());
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "q")
{
cpp_member_function_type::builder builder(cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_builtin_type::build(cpp_void));
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_builtin_type::build(cpp_void));
builder.add_parameter(cpp_builtin_type::build(cpp_int));
auto type = cpp_pointer_type::build(builder.finish());
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "r")
{
auto obj = cpp_reference_type::build(add_cv(cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_cv_const),
cpp_ref_lvalue);
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_cv_const),
cpp_ref_lvalue);
cpp_member_function_type::builder builder(std::move(obj),
cpp_builtin_type::build(cpp_void));
cpp_builtin_type::build(cpp_void));
builder.add_parameter(cpp_builtin_type::build(cpp_int));
builder.is_variadic();
auto type = cpp_pointer_type::build(builder.finish());
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else if (alias.name() == "s")
{
// in old libclang version, the member type isn't exposed for some reason
auto pointee
= cpp_member_object_type::build(cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_unexposed_type::build("int"));
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_unexposed_type::build("int"));
auto type = cpp_pointer_type::build(std::move(pointee));
auto is_unexposed = equal_types(idx, alias.underlying_type(), *type);
if (!is_unexposed)
{
pointee = cpp_member_object_type::build(cpp_user_defined_type::build(
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_builtin_type::build(cpp_int));
cpp_type_ref(cpp_entity_id(""), "foo")),
cpp_builtin_type::build(cpp_int));
type = cpp_pointer_type::build(std::move(pointee));
auto is_builtin = equal_types(idx, alias.underlying_type(), *type);
REQUIRE(is_builtin);
CHECK(is_builtin);
}
}
else if (alias.name() == "t")
{
auto type = cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "t_"));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
return false; // inhibit comment check for next three entities
// as they can't be documented (will always apply to the inline type)
}
else if (alias.name() == "u")
{
auto type = cpp_pointer_type::build(
add_cv(cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "u_")),
cpp_cv_const));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
add_cv(cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "u_")),
cpp_cv_const));
CHECK(equal_types(idx, alias.underlying_type(), *type));
return false;
}
else if (alias.name() == "v")
{
auto type = cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), ""));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
CHECK(equal_types(idx, alias.underlying_type(), *type));
return false;
}
else if (alias.name() == "w")
{
auto type = cpp_decltype_type::build(
cpp_unexposed_expression::build(cpp_builtin_type::build(cpp_int),
cpp_token_string::tokenize("0")));
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
cpp_unexposed_expression::build(cpp_builtin_type::build(cpp_int),
cpp_token_string::tokenize("0")));
CHECK(equal_types(idx, alias.underlying_type(), *type));
}
else
REQUIRE(false);
CHECK(false);
return check_code;
});
REQUIRE(count == 23u);
REQUIRE(count == 24u);
}