[cfe-commits] [libcxxabi] r148713 - in /libcxxabi/trunk/src: private_typeinfo.cpp private_typeinfo.h

Howard Hinnant hhinnant at apple.com
Mon Jan 23 10:39:47 PST 2012


Author: hhinnant
Date: Mon Jan 23 12:39:47 2012
New Revision: 148713

URL: http://llvm.org/viewvc/llvm-project?rev=148713&view=rev
Log:
I'm beginning to be able to throw/catch a wide variety of objects.

Modified:
    libcxxabi/trunk/src/private_typeinfo.cpp
    libcxxabi/trunk/src/private_typeinfo.h

Modified: libcxxabi/trunk/src/private_typeinfo.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=148713&r1=148712&r2=148713&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.cpp (original)
+++ libcxxabi/trunk/src/private_typeinfo.cpp Mon Jan 23 12:39:47 2012
@@ -201,16 +201,17 @@
 // 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 @@
     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)

Modified: libcxxabi/trunk/src/private_typeinfo.h
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.h?rev=148713&r1=148712&r2=148713&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.h (original)
+++ libcxxabi/trunk/src/private_typeinfo.h Mon Jan 23 12:39:47 2012
@@ -33,6 +33,7 @@
 {
 public:
     virtual ~__fundamental_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
     virtual void display() const;
 };
 
@@ -41,6 +42,7 @@
 {
 public:
     virtual ~__array_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
     virtual void display() const;
 };
 
@@ -49,6 +51,7 @@
 {
 public:
     virtual ~__function_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
     virtual void display() const;
 };
 
@@ -57,6 +60,7 @@
 {
 public:
     virtual ~__enum_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
     virtual void display() const;
 };
 
@@ -127,8 +131,11 @@
 
     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 @@
 
     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 @@
 
     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 @@
 
     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 @@
     };
 
     virtual ~__pbase_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
 };
 
 class __pointer_type_info
@@ -212,6 +223,7 @@
 {
 public:
     virtual ~__pointer_type_info();
+    virtual bool can_catch(const __shim_type_info*, void*&) const;
     virtual void display() const;
 };
 





More information about the cfe-commits mailing list