Add support for array types
This commit is contained in:
parent
b183513166
commit
0eb14d8cab
4 changed files with 111 additions and 11 deletions
|
|
@ -15,6 +15,7 @@ namespace cppast
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// \returns A newly created array.
|
/// \returns A newly created array.
|
||||||
|
/// \notes `size` may be `nullptr`.
|
||||||
static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type,
|
static std::unique_ptr<cpp_array_type> build(std::unique_ptr<cpp_type> type,
|
||||||
std::unique_ptr<cpp_expression> size)
|
std::unique_ptr<cpp_expression> size)
|
||||||
{
|
{
|
||||||
|
|
@ -28,10 +29,11 @@ namespace cppast
|
||||||
return *type_;
|
return *type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns A [cppast::cpp_expression]() that is the size of the array.
|
/// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the array.
|
||||||
const cpp_expression& size() const noexcept
|
/// \notes An unsized array - `T[]` - does not have a size.
|
||||||
|
type_safe::optional_ref<const cpp_expression> size() const noexcept
|
||||||
{
|
{
|
||||||
return *size_;
|
return type_safe::opt_cref(size_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace cppast
|
||||||
/// An unexposed [cppast::cpp_expression]().
|
/// An unexposed [cppast::cpp_expression]().
|
||||||
///
|
///
|
||||||
/// There is no further information than a string available.
|
/// There is no further information than a string available.
|
||||||
class cpp_unexposed_expression final : cpp_expression
|
class cpp_unexposed_expression final : public cpp_expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// \returns A newly created unexposed expression.
|
/// \returns A newly created unexposed expression.
|
||||||
|
|
@ -90,7 +90,7 @@ namespace cppast
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A [cppast::cpp_expression]() that is a literal.
|
/// A [cppast::cpp_expression]() that is a literal.
|
||||||
class cpp_literal_expression final : cpp_expression
|
class cpp_literal_expression final : public cpp_expression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// \returns A newly created literal expression.
|
/// \returns A newly created literal expression.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "parse_functions.hpp"
|
#include "parse_functions.hpp"
|
||||||
|
|
||||||
#include <cppast/cpp_array_type.hpp>
|
#include <cppast/cpp_array_type.hpp>
|
||||||
|
#include <cppast/cpp_expression.hpp>
|
||||||
#include <cppast/cpp_function_type.hpp>
|
#include <cppast/cpp_function_type.hpp>
|
||||||
#include <cppast/cpp_type.hpp>
|
#include <cppast/cpp_type.hpp>
|
||||||
#include <cppast/cpp_type_alias.hpp>
|
#include <cppast/cpp_type_alias.hpp>
|
||||||
|
|
@ -174,6 +175,37 @@ namespace
|
||||||
return cpp_ref_none;
|
return cpp_ref_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<cpp_expression> parse_array_size(const CXType& type)
|
||||||
|
{
|
||||||
|
auto size = clang_getArraySize(type);
|
||||||
|
if (size != -1)
|
||||||
|
return cpp_literal_expression::build(cpp_builtin_type::build("unsigned long long"),
|
||||||
|
std::to_string(size));
|
||||||
|
|
||||||
|
auto spelling = get_type_spelling(type);
|
||||||
|
DEBUG_ASSERT(spelling.size() > 2u && spelling.back() == ']', detail::parse_error_handler{},
|
||||||
|
type, "unexpected token");
|
||||||
|
|
||||||
|
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)
|
||||||
|
size_expr += *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size_expr.empty() ?
|
||||||
|
nullptr :
|
||||||
|
cpp_unexposed_expression::build(cpp_builtin_type::build("unsigned long long"),
|
||||||
|
std::string(size_expr.rbegin(),
|
||||||
|
size_expr.rend()));
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context,
|
std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context,
|
||||||
const CXType& type)
|
const CXType& type)
|
||||||
{
|
{
|
||||||
|
|
@ -255,15 +287,17 @@ namespace
|
||||||
return cpp_reference_type::build(std::move(referee), get_reference_kind(type));
|
return cpp_reference_type::build(std::move(referee), get_reference_kind(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
case CXType_IncompleteArray:
|
case CXType_IncompleteArray:
|
||||||
case CXType_VariableArray:
|
case CXType_VariableArray:
|
||||||
case CXType_DependentSizedArray:
|
case CXType_DependentSizedArray:
|
||||||
case CXType_ConstantArray:
|
case CXType_ConstantArray:
|
||||||
{
|
{
|
||||||
break;
|
auto size = parse_array_size(type);
|
||||||
|
auto value_type = parse_type_impl(context, clang_getArrayElementType(type));
|
||||||
|
return cpp_array_type::build(std::move(value_type), std::move(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
case CXType_Dependent:
|
case CXType_Dependent:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -283,13 +317,18 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_type> detail::parse_type(const detail::parse_context& context,
|
std::unique_ptr<cpp_type> detail::parse_type(const detail::parse_context& context,
|
||||||
const CXType& type)
|
const CXType& type) try
|
||||||
{
|
{
|
||||||
auto result = parse_type_impl(context, type);
|
auto result = parse_type_impl(context, type);
|
||||||
DEBUG_ASSERT(result && is_valid(*result), detail::parse_error_handler{}, type,
|
DEBUG_ASSERT(result && is_valid(*result), detail::parse_error_handler{}, type,
|
||||||
"invalid type parsed");
|
"invalid type parsed");
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
catch (parse_error& ex)
|
||||||
|
{
|
||||||
|
context.logger->log("libclang parser", ex.get_diagnostic());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_entity> detail::parse_cpp_type_alias(const detail::parse_context& context,
|
std::unique_ptr<cpp_entity> detail::parse_cpp_type_alias(const detail::parse_context& context,
|
||||||
const CXCursor& cur)
|
const CXCursor& cur)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include <cppast/cpp_type_alias.hpp>
|
#include <cppast/cpp_type_alias.hpp>
|
||||||
|
|
||||||
|
#include <cppast/cpp_array_type.hpp>
|
||||||
|
|
||||||
#include "test_parser.hpp"
|
#include "test_parser.hpp"
|
||||||
|
|
||||||
using namespace cppast;
|
using namespace cppast;
|
||||||
|
|
@ -49,9 +51,34 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
|
||||||
&& equal_types(idx, ref_a.referee(), ref_b.referee());
|
&& equal_types(idx, ref_a.referee(), ref_b.referee());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
case cpp_type_kind::array:
|
case cpp_type_kind::array:
|
||||||
break;
|
{
|
||||||
|
auto& array_a = static_cast<const cpp_array_type&>(parsed);
|
||||||
|
auto& array_b = static_cast<const cpp_array_type&>(synthesized);
|
||||||
|
|
||||||
|
// check value type
|
||||||
|
if (!equal_types(idx, array_a.value_type(), array_b.value_type()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check size
|
||||||
|
if (!array_a.size().has_value() && !array_b.size().has_value())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto& size_a = array_a.size().value();
|
||||||
|
auto& size_b = array_b.size().value();
|
||||||
|
if (size_a.kind() != size_b.kind())
|
||||||
|
return false;
|
||||||
|
else if (size_a.kind() == cpp_expression_kind::literal)
|
||||||
|
return static_cast<const cpp_literal_expression&>(size_a).value()
|
||||||
|
== static_cast<const cpp_literal_expression&>(size_b).value();
|
||||||
|
else if (size_a.kind() == cpp_expression_kind::unexposed)
|
||||||
|
return static_cast<const cpp_unexposed_expression&>(size_a).expression()
|
||||||
|
== static_cast<const cpp_unexposed_expression&>(size_b).expression();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
case cpp_type_kind::function:
|
case cpp_type_kind::function:
|
||||||
break;
|
break;
|
||||||
case cpp_type_kind::member_function:
|
case cpp_type_kind::member_function:
|
||||||
|
|
@ -95,12 +122,25 @@ using g = const int&&;
|
||||||
using h = c;
|
using h = c;
|
||||||
using i = const d;
|
using i = const d;
|
||||||
using j = e*;
|
using j = e*;
|
||||||
|
|
||||||
|
// arrays
|
||||||
|
using k = int[42];
|
||||||
|
using l = float*[];
|
||||||
|
using m = char[3 * 2 + 4 ? 42 : 43];
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto add_cv = [](std::unique_ptr<cpp_type> type, cpp_cv cv) {
|
auto add_cv = [](std::unique_ptr<cpp_type> type, cpp_cv cv) {
|
||||||
return cpp_cv_qualified_type::build(std::move(type), cv);
|
return cpp_cv_qualified_type::build(std::move(type), cv);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto make_size = [](std::string size, bool literal) -> std::unique_ptr<cpp_expression> {
|
||||||
|
auto type = cpp_builtin_type::build("unsigned long long");
|
||||||
|
if (literal)
|
||||||
|
return cpp_literal_expression::build(std::move(type), std::move(size));
|
||||||
|
else
|
||||||
|
return cpp_unexposed_expression::build(std::move(type), std::move(size));
|
||||||
|
};
|
||||||
|
|
||||||
cpp_entity_index idx;
|
cpp_entity_index idx;
|
||||||
auto file = parse(idx, "cpp_type_alias.cpp", code);
|
auto file = parse(idx, "cpp_type_alias.cpp", code);
|
||||||
auto count = test_visit<cpp_type_alias>(*file, [&](const cpp_type_alias& alias) {
|
auto count = test_visit<cpp_type_alias>(*file, [&](const cpp_type_alias& alias) {
|
||||||
|
|
@ -161,8 +201,27 @@ using j = e*;
|
||||||
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));
|
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
|
||||||
}
|
}
|
||||||
|
else if (alias.name() == "k")
|
||||||
|
{
|
||||||
|
auto type =
|
||||||
|
cpp_array_type::build(cpp_builtin_type::build("int"), make_size("42", true));
|
||||||
|
REQUIRE(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("float")),
|
||||||
|
nullptr);
|
||||||
|
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
|
||||||
|
}
|
||||||
|
else if (alias.name() == "m")
|
||||||
|
{
|
||||||
|
auto type =
|
||||||
|
cpp_array_type::build(cpp_builtin_type::build("char"), make_size("42", true));
|
||||||
|
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
});
|
});
|
||||||
REQUIRE(count == 10u);
|
REQUIRE(count == 13u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue