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

@ -116,8 +116,10 @@ std::string get_type_spelling(const CXCursor& cur, const CXType& type)
}; };
*/ */
// auto canonical = detail::cxstring(clang_getTypeSpelling(clang_getCanonicalType(type))).std_str(); // auto canonical =
// auto declaration = detail::cxstring(clang_getCursorSpelling(clang_getTypeDeclaration(type))).std_str(); // detail::cxstring(clang_getTypeSpelling(clang_getCanonicalType(type))).std_str(); auto
// declaration =
// detail::cxstring(clang_getCursorSpelling(clang_getTypeDeclaration(type))).std_str();
auto spelling = detail::cxstring(clang_getTypeSpelling(type)).std_str(); auto spelling = detail::cxstring(clang_getTypeSpelling(type)).std_str();
if (need_to_remove_scope(cur, type)) if (need_to_remove_scope(cur, type))
{ {
@ -270,16 +272,32 @@ std::unique_ptr<cpp_expression> parse_array_size(const CXCursor& cur, const CXTy
type, "unexpected token"); type, "unexpected token");
std::string size_expr; std::string size_expr;
auto bracket_count = 1;
for (auto ptr = spelling.c_str() + spelling.size() - 2u; bracket_count != 0; --ptr)
{
if (*ptr == ']')
++bracket_count;
else if (*ptr == '[')
--bracket_count;
if (bracket_count != 0) auto ptr = spelling.rbegin();
size_expr += *ptr; while (true)
{
// Consume the final closing ].
++ptr;
auto bracket_count = 1;
while (bracket_count != 0)
{
if (*ptr == ']')
++bracket_count;
else if (*ptr == '[')
--bracket_count;
if (bracket_count != 0)
size_expr += *ptr;
++ptr;
}
if (ptr == spelling.rend() || *ptr != ']')
// We don't have another ].
break;
// We do have another ], as we want the innermost, we need to restart.
size_expr.clear();
} }
return size_expr.empty() return size_expr.empty()
@ -662,8 +680,7 @@ std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context,
cpp_type_ref(detail::get_entity_id(decl), std::move(spelling))); cpp_type_ref(detail::get_entity_id(decl), std::move(spelling)));
}); });
case CXType_Pointer: case CXType_Pointer: {
{
auto pointee = parse_type_impl(context, cur, clang_getPointeeType(type)); auto pointee = parse_type_impl(context, cur, clang_getPointeeType(type));
auto pointer = cpp_pointer_type::build(std::move(pointee)); auto pointer = cpp_pointer_type::build(std::move(pointee));
@ -672,8 +689,7 @@ std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context,
return make_cv_qualified(std::move(pointer), cv); return make_cv_qualified(std::move(pointer), cv);
} }
case CXType_LValueReference: case CXType_LValueReference:
case CXType_RValueReference: case CXType_RValueReference: {
{
auto referee = parse_type_impl(context, cur, clang_getPointeeType(type)); auto referee = parse_type_impl(context, cur, clang_getPointeeType(type));
return cpp_reference_type::build(std::move(referee), get_reference_kind(type)); return cpp_reference_type::build(std::move(referee), get_reference_kind(type));
} }

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