Add support for function types
This commit is contained in:
parent
0eb14d8cab
commit
8bb6268626
4 changed files with 95 additions and 44 deletions
|
|
@ -11,23 +11,6 @@ namespace cppast
|
||||||
{
|
{
|
||||||
enum class cpp_entity_kind;
|
enum class cpp_entity_kind;
|
||||||
|
|
||||||
/// \exclude
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
void check_entity_cast_impl(const cpp_entity& e, cpp_entity_kind expected_kind);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void check_entity_cast(const cpp_entity& e)
|
|
||||||
{
|
|
||||||
check_entity_cast_impl(e, T::kind());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline void check_entity_cast<cpp_entity>(const cpp_entity&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/// A basic reference to some kind of [cppast::cpp_entity]().
|
/// A basic reference to some kind of [cppast::cpp_entity]().
|
||||||
template <typename T, typename Predicate>
|
template <typename T, typename Predicate>
|
||||||
class basic_cpp_entity_ref
|
class basic_cpp_entity_ref
|
||||||
|
|
@ -57,7 +40,8 @@ namespace cppast
|
||||||
auto entity = idx.lookup(target_);
|
auto entity = idx.lookup(target_);
|
||||||
if (!entity)
|
if (!entity)
|
||||||
return type_safe::nullopt;
|
return type_safe::nullopt;
|
||||||
detail::check_entity_cast<T>(entity.value());
|
DEBUG_ASSERT(Predicate{}(entity.value()), detail::precondition_error_handler{},
|
||||||
|
"predicate not fulfilled");
|
||||||
return static_cast<const T&>(entity.value());
|
return static_cast<const T&>(entity.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// Copyright (C) 2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
|
|
||||||
// This file is subject to the license terms in the LICENSE file
|
|
||||||
// found in the top-level directory of this distribution.
|
|
||||||
|
|
||||||
#include <cppast/cpp_entity_ref.hpp>
|
|
||||||
|
|
||||||
#include <cppast/cpp_entity.hpp>
|
|
||||||
|
|
||||||
using namespace cppast;
|
|
||||||
|
|
||||||
void detail::check_entity_cast_impl(const cpp_entity& e, cpp_entity_kind expected_kind)
|
|
||||||
{
|
|
||||||
DEBUG_ASSERT(e.kind() == expected_kind, detail::precondition_error_handler{},
|
|
||||||
"mismatched entity kind");
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#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>
|
||||||
|
#include <clang-c/Index.h>
|
||||||
|
|
||||||
using namespace cppast;
|
using namespace cppast;
|
||||||
|
|
||||||
|
|
@ -206,6 +207,28 @@ namespace
|
||||||
size_expr.rend()));
|
size_expr.rend()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<cpp_type> try_parse_function_type(const detail::parse_context& context,
|
||||||
|
const CXType& type)
|
||||||
|
{
|
||||||
|
auto result = clang_getResultType(type);
|
||||||
|
if (result.kind == CXType_Invalid)
|
||||||
|
// not a function type
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
cpp_function_type::builder builder(parse_type(context, result));
|
||||||
|
|
||||||
|
auto no_args = clang_getNumArgTypes(type);
|
||||||
|
DEBUG_ASSERT(no_args >= 0, detail::parse_error_handler{}, type,
|
||||||
|
"invalid number of arguments");
|
||||||
|
for (auto i = 0u; i != unsigned(no_args); ++i)
|
||||||
|
builder.add_parameter(detail::parse_type(context, clang_getArgType(type, i)));
|
||||||
|
|
||||||
|
if (clang_isFunctionTypeVariadic(type))
|
||||||
|
builder.is_variadic();
|
||||||
|
|
||||||
|
return builder.finish();
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
@ -231,6 +254,10 @@ namespace
|
||||||
}
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case CXType_Unexposed:
|
case CXType_Unexposed:
|
||||||
|
if (auto ftype = try_parse_function_type(context, type))
|
||||||
|
// guess what: after you've called clang_getPointeeType() on a function pointer
|
||||||
|
// you'll get an unexposed type
|
||||||
|
return ftype;
|
||||||
return cpp_unexposed_type::build(get_type_spelling(type).c_str());
|
return cpp_unexposed_type::build(get_type_spelling(type).c_str());
|
||||||
|
|
||||||
case CXType_Void:
|
case CXType_Void:
|
||||||
|
|
@ -273,7 +300,7 @@ namespace
|
||||||
|
|
||||||
case CXType_Pointer:
|
case CXType_Pointer:
|
||||||
{
|
{
|
||||||
auto pointee = parse_type_impl(context, clang_getPointeeType(type));
|
auto pointee = parse_type(context, clang_getPointeeType(type));
|
||||||
auto pointer = cpp_pointer_type::build(std::move(pointee));
|
auto pointer = cpp_pointer_type::build(std::move(pointee));
|
||||||
|
|
||||||
auto spelling = get_type_spelling(type);
|
auto spelling = get_type_spelling(type);
|
||||||
|
|
@ -283,7 +310,7 @@ namespace
|
||||||
case CXType_LValueReference:
|
case CXType_LValueReference:
|
||||||
case CXType_RValueReference:
|
case CXType_RValueReference:
|
||||||
{
|
{
|
||||||
auto referee = parse_type_impl(context, clang_getPointeeType(type));
|
auto referee = parse_type(context, 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,18 +320,17 @@ namespace
|
||||||
case CXType_ConstantArray:
|
case CXType_ConstantArray:
|
||||||
{
|
{
|
||||||
auto size = parse_array_size(type);
|
auto size = parse_array_size(type);
|
||||||
auto value_type = parse_type_impl(context, clang_getArrayElementType(type));
|
auto value_type = parse_type(context, clang_getArrayElementType(type));
|
||||||
return cpp_array_type::build(std::move(value_type), std::move(size));
|
return cpp_array_type::build(std::move(value_type), std::move(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CXType_FunctionNoProto:
|
||||||
|
case CXType_FunctionProto:
|
||||||
|
return try_parse_function_type(context, type);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
case CXType_Dependent:
|
case CXType_Dependent:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CXType_FunctionNoProto:
|
|
||||||
break;
|
|
||||||
case CXType_FunctionProto:
|
|
||||||
break;
|
|
||||||
case CXType_MemberPointer:
|
case CXType_MemberPointer:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cppast/cpp_type_alias.hpp>
|
#include <cppast/cpp_type_alias.hpp>
|
||||||
|
|
||||||
#include <cppast/cpp_array_type.hpp>
|
#include <cppast/cpp_array_type.hpp>
|
||||||
|
#include <cppast/cpp_function_type.hpp>
|
||||||
|
|
||||||
#include "test_parser.hpp"
|
#include "test_parser.hpp"
|
||||||
|
|
||||||
|
|
@ -78,9 +79,29 @@ bool equal_types(const cpp_entity_index& idx, const cpp_type& parsed, const cpp_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
case cpp_type_kind::function:
|
case cpp_type_kind::function:
|
||||||
break;
|
{
|
||||||
|
auto& func_a = static_cast<const cpp_function_type&>(parsed);
|
||||||
|
auto& func_b = static_cast<const cpp_function_type&>(synthesized);
|
||||||
|
|
||||||
|
if (!equal_types(idx, func_a.return_type(), func_b.return_type()))
|
||||||
|
return false;
|
||||||
|
else if (func_a.is_variadic() != func_b.is_variadic())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto iter_a = func_a.parameter_types().begin();
|
||||||
|
auto iter_b = func_a.parameter_types().begin();
|
||||||
|
while (iter_a != func_a.parameter_types().end() && iter_b != func_b.parameter_types().end())
|
||||||
|
{
|
||||||
|
if (!equal_types(idx, *iter_a, *iter_b))
|
||||||
|
return false;
|
||||||
|
++iter_a;
|
||||||
|
++iter_b;
|
||||||
|
}
|
||||||
|
return iter_a == func_a.parameter_types().end() && iter_b == func_b.parameter_types().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
case cpp_type_kind::member_function:
|
case cpp_type_kind::member_function:
|
||||||
break;
|
break;
|
||||||
case cpp_type_kind::member_object:
|
case cpp_type_kind::member_object:
|
||||||
|
|
@ -127,6 +148,11 @@ using j = e*;
|
||||||
using k = int[42];
|
using k = int[42];
|
||||||
using l = float*[];
|
using l = float*[];
|
||||||
using m = char[3 * 2 + 4 ? 42 : 43];
|
using m = char[3 * 2 + 4 ? 42 : 43];
|
||||||
|
|
||||||
|
// function pointers
|
||||||
|
using n = void(*)(int);
|
||||||
|
using o = char*(&)(int&,...);
|
||||||
|
using p = n(*)(int, o);
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto add_cv = [](std::unique_ptr<cpp_type> type, cpp_cv cv) {
|
auto add_cv = [](std::unique_ptr<cpp_type> type, cpp_cv cv) {
|
||||||
|
|
@ -220,8 +246,38 @@ using m = char[3 * 2 + 4 ? 42 : 43];
|
||||||
cpp_array_type::build(cpp_builtin_type::build("char"), make_size("42", true));
|
cpp_array_type::build(cpp_builtin_type::build("char"), make_size("42", true));
|
||||||
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
|
REQUIRE(equal_types(idx, alias.underlying_type(), *type));
|
||||||
}
|
}
|
||||||
|
else if (alias.name() == "n")
|
||||||
|
{
|
||||||
|
cpp_function_type::builder builder(cpp_builtin_type::build("void"));
|
||||||
|
builder.add_parameter(cpp_builtin_type::build("int"));
|
||||||
|
auto type = cpp_pointer_type::build(builder.finish());
|
||||||
|
|
||||||
|
REQUIRE(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("char")));
|
||||||
|
builder.add_parameter(
|
||||||
|
cpp_reference_type::build(cpp_builtin_type::build("int"), 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));
|
||||||
|
}
|
||||||
|
else if (alias.name() == "p")
|
||||||
|
{
|
||||||
|
cpp_function_type::builder builder(
|
||||||
|
cpp_user_defined_type::build(cpp_type_ref(cpp_entity_id(""), "n")));
|
||||||
|
builder.add_parameter(cpp_builtin_type::build("int"));
|
||||||
|
builder.add_parameter(
|
||||||
|
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));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
});
|
});
|
||||||
REQUIRE(count == 13u);
|
REQUIRE(count == 16u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue