Add is_valid() check for types
This commit is contained in:
parent
78d546f09c
commit
36425c096b
2 changed files with 99 additions and 0 deletions
|
|
@ -61,6 +61,10 @@ namespace cppast
|
|||
friend detail::intrusive_list_node<cpp_type>;
|
||||
};
|
||||
|
||||
/// \returns `true` if the given [cppast::cpp_type]() is valid, `false` otherwise.
|
||||
/// Invalid types are, for example, references to references.
|
||||
bool is_valid(const cpp_type& type) noexcept;
|
||||
|
||||
/// An unexposed [cppast::cpp_type]().
|
||||
///
|
||||
/// This is one where no further information besides a name is available.
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
|
||||
#include <cppast/cpp_type.hpp>
|
||||
|
||||
#include <cppast/cpp_array_type.hpp>
|
||||
#include <cppast/cpp_entity.hpp>
|
||||
#include <cppast/cpp_entity_type.hpp>
|
||||
#include <cppast/cpp_function_types.hpp>
|
||||
|
||||
using namespace cppast;
|
||||
|
||||
|
|
@ -13,3 +15,96 @@ bool detail::cpp_type_ref_predicate::operator()(const cpp_entity& e)
|
|||
{
|
||||
return is_type(e.type());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool can_compose(const cpp_type& type)
|
||||
{
|
||||
return type.kind() != cpp_type_kind::function
|
||||
&& type.kind() != cpp_type_kind::member_function
|
||||
&& type.kind() != cpp_type_kind::member_object;
|
||||
}
|
||||
}
|
||||
|
||||
bool cppast::is_valid(const cpp_type& type) noexcept
|
||||
{
|
||||
switch (type.kind())
|
||||
{
|
||||
case cpp_type_kind::cv_qualified:
|
||||
{
|
||||
auto& qual = static_cast<const cpp_cv_qualified_type&>(type);
|
||||
if (qual.type().kind() == cpp_type_kind::reference)
|
||||
return false; // not allowed
|
||||
return is_valid(qual.type());
|
||||
}
|
||||
case cpp_type_kind::pointer:
|
||||
{
|
||||
auto& ptr = static_cast<const cpp_pointer_type&>(type);
|
||||
if (ptr.pointee().kind() == cpp_type_kind::reference)
|
||||
return false; // not allowed
|
||||
return is_valid(ptr.pointee());
|
||||
}
|
||||
case cpp_type_kind::reference:
|
||||
{
|
||||
auto& ref = static_cast<const cpp_reference_type&>(type);
|
||||
if (ref.referee().kind() == cpp_type_kind::member_function
|
||||
|| ref.referee().kind() == cpp_type_kind::member_object)
|
||||
return false; // not allowed
|
||||
return is_valid(ref.referee());
|
||||
}
|
||||
|
||||
case cpp_type_kind::array:
|
||||
{
|
||||
auto& array = static_cast<const cpp_array_type&>(type);
|
||||
if (array.value_type().kind() == cpp_type_kind::reference
|
||||
|| !can_compose(array.value_type()))
|
||||
return false;
|
||||
return is_valid(array.value_type());
|
||||
}
|
||||
|
||||
case cpp_type_kind::function:
|
||||
{
|
||||
auto& func = static_cast<const cpp_function_type&>(type);
|
||||
|
||||
if (!can_compose(func.return_type()) || !is_valid(func.return_type()))
|
||||
return false;
|
||||
|
||||
for (auto& arg : func.argument_types())
|
||||
if (!can_compose(arg) || !is_valid(arg))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
case cpp_type_kind::member_function:
|
||||
{
|
||||
auto& func = static_cast<const cpp_member_function_type&>(type);
|
||||
|
||||
if (func.class_type().kind() != cpp_type_kind::user_defined)
|
||||
return false;
|
||||
else if (!can_compose(func.return_type()) || !is_valid(func.return_type()))
|
||||
return false;
|
||||
|
||||
for (auto& arg : func.argument_types())
|
||||
if (!can_compose(arg) || !is_valid(arg))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
case cpp_type_kind::member_object:
|
||||
{
|
||||
auto& obj = static_cast<const cpp_member_object_type&>(type);
|
||||
|
||||
if (obj.class_type().kind() != cpp_type_kind::user_defined)
|
||||
return false;
|
||||
return is_valid(obj.object_type());
|
||||
}
|
||||
|
||||
case cpp_type_kind::builtin:
|
||||
case cpp_type_kind::user_defined:
|
||||
case cpp_type_kind::unexposed:
|
||||
// no further check required/possible
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue