mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-19 09:26:59 +00:00
I'm beginning to be able to throw/catch a wide variety of objects.
llvm-svn: 148713
This commit is contained in:
parent
880bc1644b
commit
53418916fc
@ -201,16 +201,17 @@ __pointer_to_member_type_info::display() const
|
||||
// can_catch
|
||||
|
||||
// A handler is a match for an exception object of type E if
|
||||
// * The handler is of type cv T or cv T& and E and T are the same type
|
||||
// (ignoring the top-level cv-qualifiers), or
|
||||
// * the handler is of type cv T or cv T& and T is an unambiguous public
|
||||
// base class of E, or
|
||||
// * the handler is of type cv1 T* cv2 and E is a pointer type that can be
|
||||
// converted to the type of the handler by either or both of
|
||||
// * a standard pointer conversion (4.10) not involving conversions to
|
||||
// pointers to private or protected or ambiguous classes
|
||||
// * a qualification conversion
|
||||
// * the handler is a pointer or pointer to member type and E is std::nullptr_t.
|
||||
// 1. The handler is of type cv T or cv T& and E and T are the same type
|
||||
// (ignoring the top-level cv-qualifiers), or
|
||||
// 2. the handler is of type cv T or cv T& and T is an unambiguous public
|
||||
// base class of E, or
|
||||
// 3. the handler is of type cv1 T* cv2 and E is a pointer type that can be
|
||||
// converted to the type of the handler by either or both of
|
||||
// A. a standard pointer conversion (4.10) not involving conversions to
|
||||
// pointers to private or protected or ambiguous classes
|
||||
// B. a qualification conversion
|
||||
// 4. the handler is a pointer or pointer to member type and E is
|
||||
// std::nullptr_t.
|
||||
|
||||
// adjustedPtr:
|
||||
//
|
||||
@ -233,6 +234,207 @@ __shim_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
return this == thrown_type;
|
||||
}
|
||||
|
||||
// Handles bullet 1
|
||||
// TODO: Let __shim_type_info handle it?
|
||||
bool
|
||||
__fundamental_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*&) const
|
||||
{
|
||||
return this == thrown_type;
|
||||
}
|
||||
|
||||
bool
|
||||
__array_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*&) const
|
||||
{
|
||||
// TODO: Can this be called?
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
__function_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*&) const
|
||||
{
|
||||
// TODO: Can this be called?
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handles bullet 1
|
||||
// TODO: Let __shim_type_info handle it?
|
||||
bool
|
||||
__enum_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*&) const
|
||||
{
|
||||
return this == thrown_type;
|
||||
}
|
||||
|
||||
// Handles bullets 1 and 2
|
||||
bool
|
||||
__class_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*& adjustedPtr) const
|
||||
{
|
||||
// bullet 1
|
||||
if (this == thrown_type)
|
||||
return true;
|
||||
const __class_type_info* thrown_class_type =
|
||||
dynamic_cast<const __class_type_info*>(thrown_type);
|
||||
if (thrown_class_type == 0)
|
||||
return false;
|
||||
// bullet 2
|
||||
__dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0};
|
||||
info.number_of_dst_type = 1;
|
||||
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
{
|
||||
adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
__class_type_info::process_found_base_class(__dynamic_cast_info* info,
|
||||
void* adjustedPtr,
|
||||
int path_below) const
|
||||
{
|
||||
if (info->dst_ptr_leading_to_static_ptr == 0)
|
||||
{
|
||||
// First time here
|
||||
info->dst_ptr_leading_to_static_ptr = adjustedPtr;
|
||||
info->path_dst_ptr_to_static_ptr = path_below;
|
||||
info->number_to_static_ptr = 1;
|
||||
}
|
||||
else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
|
||||
{
|
||||
// We've been here before. Update path to "most public"
|
||||
if (info->path_dst_ptr_to_static_ptr == not_public_path)
|
||||
info->path_dst_ptr_to_static_ptr = path_below;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
|
||||
// to a static_type
|
||||
info->number_to_static_ptr += 1;
|
||||
info->path_dst_ptr_to_static_ptr = not_public_path;
|
||||
info->search_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
|
||||
void* adjustedPtr,
|
||||
int path_below) const
|
||||
{
|
||||
if (this == info->static_type)
|
||||
process_found_base_class(info, adjustedPtr, path_below);
|
||||
}
|
||||
|
||||
void
|
||||
__si_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
|
||||
void* adjustedPtr,
|
||||
int path_below) const
|
||||
{
|
||||
if (this == info->static_type)
|
||||
process_found_base_class(info, adjustedPtr, path_below);
|
||||
else
|
||||
__base_type->has_unambiguous_public_base(info, adjustedPtr, path_below);
|
||||
}
|
||||
|
||||
void
|
||||
__base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
|
||||
void* adjustedPtr,
|
||||
int path_below) const
|
||||
{
|
||||
ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
|
||||
if (__offset_flags & __virtual_mask)
|
||||
{
|
||||
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
|
||||
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
|
||||
}
|
||||
__base_type->has_unambiguous_public_base(info,
|
||||
static_cast<char*>(adjustedPtr) + offset_to_base,
|
||||
(__offset_flags & __public_mask) ?
|
||||
path_below :
|
||||
not_public_path);
|
||||
}
|
||||
|
||||
void
|
||||
__vmi_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
|
||||
void* adjustedPtr,
|
||||
int path_below) const
|
||||
{
|
||||
if (this == info->static_type)
|
||||
process_found_base_class(info, adjustedPtr, path_below);
|
||||
else
|
||||
{
|
||||
typedef const __base_class_type_info* Iter;
|
||||
const Iter e = __base_info + __base_count;
|
||||
Iter p = __base_info;
|
||||
p->has_unambiguous_public_base(info, adjustedPtr, path_below);
|
||||
if (++p < e)
|
||||
{
|
||||
do
|
||||
{
|
||||
p->has_unambiguous_public_base(info, adjustedPtr, path_below);
|
||||
if (info->search_done)
|
||||
break;
|
||||
} while (++p < e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles bullets 1 and 4
|
||||
// TODO: Are we good to go here for __pointer_to_member_type_info?
|
||||
bool
|
||||
__pbase_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*&) const
|
||||
{
|
||||
if (this == thrown_type)
|
||||
return true;
|
||||
return thrown_type == &typeid(std::nullptr_t);
|
||||
}
|
||||
|
||||
// Handles bullets 1, 3 and 4
|
||||
bool
|
||||
__pointer_type_info::can_catch(const __shim_type_info* thrown_type,
|
||||
void*& adjustedPtr) const
|
||||
{
|
||||
// Do the dereference adjustment
|
||||
adjustedPtr = *static_cast<void**>(adjustedPtr);
|
||||
// bullets 1 and 4
|
||||
if (__pbase_type_info::can_catch(thrown_type, adjustedPtr))
|
||||
return true;
|
||||
// bullet 3
|
||||
const __pointer_type_info* thrown_pointer_type =
|
||||
dynamic_cast<const __pointer_type_info*>(thrown_type);
|
||||
if (thrown_pointer_type == 0)
|
||||
return false;
|
||||
// bullet 3B
|
||||
if (thrown_pointer_type->__flags & ~__flags)
|
||||
return false;
|
||||
if (__pointee == thrown_pointer_type->__pointee)
|
||||
return true;
|
||||
// bullet 3A
|
||||
if (__pointee == &typeid(void))
|
||||
return true;
|
||||
const __class_type_info* catch_class_type =
|
||||
dynamic_cast<const __class_type_info*>(__pointee);
|
||||
if (catch_class_type == 0)
|
||||
return false;
|
||||
const __class_type_info* thrown_class_type =
|
||||
dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
|
||||
if (thrown_class_type == 0)
|
||||
return false;
|
||||
__dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0};
|
||||
info.number_of_dst_type = 1;
|
||||
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
{
|
||||
adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GCC visibility pop
|
||||
#pragma GCC visibility push(default)
|
||||
|
@ -33,6 +33,7 @@ class __fundamental_type_info
|
||||
{
|
||||
public:
|
||||
virtual ~__fundamental_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -41,6 +42,7 @@ class __array_type_info
|
||||
{
|
||||
public:
|
||||
virtual ~__array_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -49,6 +51,7 @@ class __function_type_info
|
||||
{
|
||||
public:
|
||||
virtual ~__function_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -57,6 +60,7 @@ class __enum_type_info
|
||||
{
|
||||
public:
|
||||
virtual ~__enum_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -127,8 +131,11 @@ public:
|
||||
|
||||
void process_static_type_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
|
||||
void process_static_type_below_dst(__dynamic_cast_info*, const void*, int) const;
|
||||
void process_found_base_class(__dynamic_cast_info*, void*, int) const;
|
||||
virtual void search_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
|
||||
virtual void search_below_dst(__dynamic_cast_info*, const void*, int) const;
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void has_unambiguous_public_base(__dynamic_cast_info*, void*, int) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -143,6 +150,7 @@ public:
|
||||
|
||||
virtual void search_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
|
||||
virtual void search_below_dst(__dynamic_cast_info*, const void*, int) const;
|
||||
virtual void has_unambiguous_public_base(__dynamic_cast_info*, void*, int) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -161,6 +169,7 @@ public:
|
||||
|
||||
void search_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
|
||||
void search_below_dst(__dynamic_cast_info*, const void*, int) const;
|
||||
void has_unambiguous_public_base(__dynamic_cast_info*, void*, int) const;
|
||||
void display() const;
|
||||
};
|
||||
|
||||
@ -185,6 +194,7 @@ public:
|
||||
|
||||
virtual void search_above_dst(__dynamic_cast_info*, const void*, const void*, int) const;
|
||||
virtual void search_below_dst(__dynamic_cast_info*, const void*, int) const;
|
||||
virtual void has_unambiguous_public_base(__dynamic_cast_info*, void*, int) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
@ -205,6 +215,7 @@ public:
|
||||
};
|
||||
|
||||
virtual ~__pbase_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
};
|
||||
|
||||
class __pointer_type_info
|
||||
@ -212,6 +223,7 @@ class __pointer_type_info
|
||||
{
|
||||
public:
|
||||
virtual ~__pointer_type_info();
|
||||
virtual bool can_catch(const __shim_type_info*, void*&) const;
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user