Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Mar 2012 17:58:15 +0000 (UTC)
From:      David Chisnall <theraven@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233235 - in head: contrib/libcxxrt lib/libcxxrt
Message-ID:  <201203201758.q2KHwFKC030826@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: theraven
Date: Tue Mar 20 17:58:15 2012
New Revision: 233235
URL: http://svn.freebsd.org/changeset/base/233235

Log:
  Import new version of libcxxrt.  Now works correctly with libobjc2 to implement
  the unified exception model for Objective-C++.
  
  Approved by:	dim (mentor)

Deleted:
  head/contrib/libcxxrt/typeinfo
Modified:
  head/contrib/libcxxrt/dynamic_cast.cc
  head/contrib/libcxxrt/exception.cc
  head/contrib/libcxxrt/typeinfo.h
  head/lib/libcxxrt/Version.map
Directory Properties:
  head/contrib/libcxxrt/   (props changed)

Modified: head/contrib/libcxxrt/dynamic_cast.cc
==============================================================================
--- head/contrib/libcxxrt/dynamic_cast.cc	Tue Mar 20 17:43:30 2012	(r233234)
+++ head/contrib/libcxxrt/dynamic_cast.cc	Tue Mar 20 17:58:15 2012	(r233235)
@@ -46,9 +46,65 @@ struct vtable_header
  */
 #define ADD_TO_PTR(x, off) (__typeof__(x))(((char*)x) + off)
 
-bool __class_type_info::can_cast_to(const struct __class_type_info *other) const
+bool std::type_info::__do_catch(std::type_info const *ex_type,
+                                void **exception_object,
+                                unsigned int outer) const
 {
-    return this == other;
+	const type_info *type = this;
+
+	if (type == ex_type)
+	{
+		return true;
+	}
+	if (const __class_type_info *cti = dynamic_cast<const __class_type_info *>(type))
+	{
+		return ex_type->__do_upcast(cti, exception_object);
+	}
+	return false;
+}
+
+bool __pbase_type_info::__do_catch(std::type_info const *ex_type,
+                                   void **exception_object,
+                                   unsigned int outer) const
+{
+	if (ex_type == this)
+	{
+		return true;
+	}
+	if (!ex_type->__is_pointer_p())
+	{
+		// Can't catch a non-pointer type in a pointer catch
+		return false;
+	}
+
+	if (!(outer & 1))
+	{
+		// If the low bit is cleared on this means that we've gone
+		// through a pointer that is not const qualified.
+		return false;
+	}
+	// Clear the low bit on outer if we're not const qualified.
+	if (!(__flags & __const_mask))
+	{
+		outer &= ~1;
+	}
+
+	const __pbase_type_info *ptr_type =
+	        static_cast<const __pbase_type_info*>(ex_type);
+
+	if (ptr_type->__flags & ~__flags)
+	{
+		// Handler pointer is less qualified
+		return false;
+	}
+
+	// Special case for void* handler.  
+	if(*__pointee == typeid(void))
+	{
+		return true;
+	}
+
+	return __pointee->__do_catch(ptr_type->__pointee, exception_object, outer);
 }
 
 void *__class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
@@ -60,12 +116,6 @@ void *__class_type_info::cast_to(void *o
 	return 0;
 }
 
-
-bool __si_class_type_info::can_cast_to(const struct __class_type_info *other) const
-{
-    return this == other || __base_type->can_cast_to(other);
-}
-
 void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
 {
 	if (this == other)
@@ -74,31 +124,32 @@ void *__si_class_type_info::cast_to(void
 	}
 	return __base_type->cast_to(obj, other);
 }
-
-
-bool __vmi_class_type_info::can_cast_to(const struct __class_type_info *other) const
+bool __si_class_type_info::__do_upcast(const __class_type_info *target,
+                                     void **thrown_object) const
 {
-	if (this == other)
+	if (this == target)
 	{
 		return true;
 	}
-	for (unsigned int i=0 ; i<__base_count ; i++)
-	{
-		const __base_class_type_info *info = &__base_info[i];
-        if(info->isPublic() && info->__base_type->can_cast_to(other))
-        {
-            return true;
-        }
-	}
-	return false;
+	return __base_type->__do_upcast(target, thrown_object);
 }
 
 void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
 {
-	if (this == other)
+	if (__do_upcast(other, &obj))
 	{
 		return obj;
 	}
+	return 0;
+}
+
+bool __vmi_class_type_info::__do_upcast(const __class_type_info *target,
+		                      void **thrown_object) const
+{
+	if (this == target)
+	{
+		return true;
+	}
 	for (unsigned int i=0 ; i<__base_count ; i++)
 	{
 		const __base_class_type_info *info = &__base_info[i];
@@ -111,6 +162,7 @@ void *__vmi_class_type_info::cast_to(voi
 		// virtual table of the virtual base offset for the virtual base
 		// referenced (negative).'
 
+		void *obj = *thrown_object;
 		if (info->isVirtual())
 		{
 			// Object's vtable
@@ -121,18 +173,17 @@ void *__vmi_class_type_info::cast_to(voi
 		}
 		void *cast = ADD_TO_PTR(obj, offset);
 
-		if (info->__base_type == other)
+		if (info->__base_type == target ||
+		    (info->__base_type->__do_upcast(target, &cast)))
 		{
-			return cast;
-		}
-		if ((cast = info->__base_type->cast_to(cast, other)))
-		{
-			return cast;
+			*thrown_object = cast;
+			return true;
 		}
 	}
 	return 0;
 }
 
+
 /**
  * ABI function used to implement the dynamic_cast<> operator.  Some cases of
  * this operator are implemented entirely in the compiler (e.g. to void*).

Modified: head/contrib/libcxxrt/exception.cc
==============================================================================
--- head/contrib/libcxxrt/exception.cc	Tue Mar 20 17:43:30 2012	(r233234)
+++ head/contrib/libcxxrt/exception.cc	Tue Mar 20 17:58:15 2012	(r233235)
@@ -847,14 +847,11 @@ static bool check_type_signature(__cxa_e
                                  const std::type_info *type,
                                  void *&adjustedPtr)
 {
-	// TODO: For compatibility with the GNU implementation, we should move this
-	// out into a __do_catch() virtual function in std::type_info
 	void *exception_ptr = (void*)(ex+1);
-    const std::type_info *ex_type = ex->exceptionType;
+	const std::type_info *ex_type = ex->exceptionType;
 
-	const __pointer_type_info *ptr_type =
-		dynamic_cast<const __pointer_type_info*>(ex_type);
-	if (0 != ptr_type)
+	bool is_ptr = ex_type->__is_pointer_p();
+	if (is_ptr)
 	{
 		exception_ptr = *(void**)exception_ptr;
 	}
@@ -862,11 +859,6 @@ static bool check_type_signature(__cxa_e
 	//
 	// Note: A 0 here is a catchall, not a cleanup, so we return true to
 	// indicate that we found a catch.
-	//
-	// TODO: Provide a class for matching against foreign exceptions.  This is
-	// already done in libobjc2, allowing C++ exceptions to be boxed as
-	// Objective-C objects.  We should do something similar, allowing foreign
-	// exceptions to be wrapped in a C++ exception and delivered.
 	if (0 == type)
 	{
 		if (ex)
@@ -878,28 +870,6 @@ static bool check_type_signature(__cxa_e
 
 	if (0 == ex) { return false; }
 
-	const __pointer_type_info *target_ptr_type =
-		dynamic_cast<const __pointer_type_info*>(type);
-
-	if (0 != ptr_type && 0 != target_ptr_type)
-	{
-		if (ptr_type->__flags & ~target_ptr_type->__flags)
-		{
-			// Handler pointer is less qualified
-			return false;
-		}
-
-		// Special case for void* handler.  
-		if(*target_ptr_type->__pointee == typeid(void))
-		{
-			adjustedPtr = exception_ptr;
-			return true;
-		}
-
-		ex_type = ptr_type->__pointee;
-		type = target_ptr_type->__pointee;
-	}
-
 	// If the types are the same, no casting is needed.
 	if (*type == *ex_type)
 	{
@@ -907,18 +877,13 @@ static bool check_type_signature(__cxa_e
 		return true;
 	}
 
-	const __class_type_info *cls_type =
-		dynamic_cast<const __class_type_info*>(ex_type);
-	const __class_type_info *target_cls_type =
-		dynamic_cast<const __class_type_info*>(type);
-
-	if (0 != cls_type &&
-		0 != target_cls_type &&
-		cls_type->can_cast_to(target_cls_type))
+
+	if (type->__do_catch(ex_type, &exception_ptr, 1))
 	{
-		adjustedPtr = cls_type->cast_to(exception_ptr, target_cls_type);
+		adjustedPtr = exception_ptr;
 		return true;
 	}
+
 	return false;
 }
 /**

Modified: head/contrib/libcxxrt/typeinfo.h
==============================================================================
--- head/contrib/libcxxrt/typeinfo.h	Tue Mar 20 17:43:30 2012	(r233234)
+++ head/contrib/libcxxrt/typeinfo.h	Tue Mar 20 17:58:15 2012	(r233235)
@@ -26,7 +26,86 @@
 
 #include <stddef.h>
 #include "abi_namespace.h"
-#include "typeinfo"
+
+namespace ABI_NAMESPACE
+{
+	struct __class_type_info;
+}
+namespace std
+{
+	/**
+	  * Standard type info class.  The layout of this class is specified by the
+	  * ABI.  The layout of the vtable is not, but is intended to be
+	  * compatible with the GNU ABI.
+	  *
+	  * Unlike the GNU version, the vtable layout is considered semi-private.
+	  */
+	class type_info
+	{
+		public:
+		/**
+		 * Virtual destructor.  This class must have one virtual function to
+		 * ensure that it has a vtable.
+		 */
+		virtual ~type_info();
+		bool operator==(const type_info &) const;
+		bool operator!=(const type_info &) const;
+		bool before(const type_info &) const;
+		const char* name() const;
+		type_info();
+		private:
+		type_info(const type_info& rhs);
+		type_info& operator= (const type_info& rhs);
+		const char *__type_name;
+		/*
+		 * The following functions are in this order to match the
+		 * vtable layout of libsupc++.  This allows libcxxrt to be used
+		 * with libraries that depend on this.
+		 *
+		 * These functions are in the public headers for libstdc++, so
+		 * we have to assume that someone will probably call them and
+		 * expect them to work.  Their names must also match the names used in
+		 * libsupc++, so that code linking against this library can subclass
+		 * type_info and correctly fill in the values in the vtables.
+		 */
+		public:
+		/**
+		 * Catch function.  Allows external libraries to implement
+		 * their own basic types.  This is used, for example, in the
+		 * GNUstep Objective-C runtime to allow Objective-C types to be
+		 * caught in G++ catch blocks.
+		 *
+		 * The outer parameter indicates the number of outer pointers
+		 * in the high bits.  The low bit indicates whether the
+		 * pointers are const qualified.
+		 */
+		virtual bool __do_catch(const type_info *thrown_type,
+		                        void **thrown_object,
+		                        unsigned outer) const;
+		/**
+		 * Performs an upcast.  This is used in exception handling to
+		 * cast from subclasses to superclasses.  If the upcast is
+		 * possible, it returns true and adjusts the pointer.  If the
+		 * upcast is not possible, it returns false and does not adjust
+		 * the pointer.
+		 */
+		virtual bool __do_upcast(
+		                const ABI_NAMESPACE::__class_type_info *target,
+		                void **thrown_object) const
+		{
+			return false;
+		}
+		/**
+		 * Returns true if this is some pointer type, false otherwise.
+		 */
+		virtual bool __is_pointer_p() const { return false; }
+		/**
+		 * Returns true if this is some function type, false otherwise.
+		 */
+		virtual bool __is_function_p() const { return false; }
+	};
+}
+
 
 namespace ABI_NAMESPACE
 {
@@ -50,6 +129,7 @@ namespace ABI_NAMESPACE
 	struct __function_type_info : public std::type_info
 	{
 		virtual ~__function_type_info();
+		virtual bool __is_function_p() const { return true; }
 	};
 	/**
 	 * Type info for enums.
@@ -68,13 +148,12 @@ namespace ABI_NAMESPACE
 		/**
 		 * Function implementing dynamic casts.
 		 */
-		virtual void *cast_to(void *obj,
-		                      const struct __class_type_info *other) const;
-		/**
-		 * Function returning whether a cast from this type to another type is
-		 * possible.
-		 */
-		virtual bool can_cast_to(const struct __class_type_info *other) const;
+		virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
+		virtual bool __do_upcast(const __class_type_info *target,
+		                       void **thrown_object) const
+		{
+			return this == target;
+		}
 	};
 
 	/**
@@ -85,8 +164,10 @@ namespace ABI_NAMESPACE
 	{
 		virtual ~__si_class_type_info();
 		const __class_type_info *__base_type;
+		virtual bool __do_upcast(
+		                const ABI_NAMESPACE::__class_type_info *target,
+		                void **thrown_object) const;
 		virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
-        virtual bool can_cast_to(const struct __class_type_info *other) const;
 	};
 
 	/**
@@ -166,8 +247,10 @@ namespace ABI_NAMESPACE
 			/** The class is diamond shaped. */
 			__diamond_shaped_mask = 0x2
 		};
+		virtual bool __do_upcast(
+		                const ABI_NAMESPACE::__class_type_info *target,
+		                void **thrown_object) const;
 		virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
-        virtual bool can_cast_to(const struct __class_type_info *other) const;
 	};
 
 	/**
@@ -201,6 +284,10 @@ namespace ABI_NAMESPACE
 			/** Pointer is a pointer to a member of an incomplete class. */
 			__incomplete_class_mask = 0x10
 		};
+		virtual bool __is_pointer_p() const { return true; }
+		virtual bool __do_catch(const type_info *thrown_type,
+		                        void **thrown_object,
+		                        unsigned outer) const;
 	};
 
 	/**

Modified: head/lib/libcxxrt/Version.map
==============================================================================
--- head/lib/libcxxrt/Version.map	Tue Mar 20 17:43:30 2012	(r233234)
+++ head/lib/libcxxrt/Version.map	Tue Mar 20 17:58:15 2012	(r233235)
@@ -301,6 +301,11 @@ CXXRT_1.0 {
         "typeinfo name for std::exception";
         "typeinfo name for std::type_info";
 
+        "std::type_info::__is_function_p() const";
+        "std::type_info::__do_upcast(__cxxabiv1::__class_type_info const*, void**) const";
+        "std::type_info::__is_pointer_p() const";
+
+
         "operator delete[](void*)";
         "operator delete(void*)";
         "operator new[](unsigned long)";



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203201758.q2KHwFKC030826>