Reactor/Traits: Fix brokenness with CToReactor::cast of pointers.

The documentation states:

  "For T types that have a CToReactorT<> specialization,
  CToReactorPtrT<T>::type resolves to Pointer< CToReactorT<T> >,
  otherwise CToReactorPtrT<T>::type resolves to Pointer<Byte>."

However, the CToReactorPtrT<T>::cast() function did not behave
correctly for some Pointer<Byte> cases. Now fixed.

Bug: b/143479561
Change-Id: I64387653e9edf21eb7fa91e3bcb7b76171c7bca4
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38389
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/Reactor.cpp b/src/Reactor/Reactor.cpp
index e217160..faa8738 100644
--- a/src/Reactor/Reactor.cpp
+++ b/src/Reactor/Reactor.cpp
@@ -4365,8 +4365,6 @@
 	Int           CToReactor<int32_t>::cast(int32_t v)         { return type(v); }
 	UInt          CToReactor<uint32_t>::cast(uint32_t v)       { return type(v); }
 	Float         CToReactor<float>::cast(float v)             { return type(v); }
-	Pointer<Byte> CToReactor<void*>::cast(void* v)             { return ConstantPointer(v); }
-	Pointer<Byte> CToReactor<const char*>::cast(const char* v) { return ConstantPointer(v); }
 
 	// TODO: Long has no constructor that takes a uint64_t
 	// Long          CToReactor<uint64_t>::cast(uint64_t v)       { return type(v); }
diff --git a/src/Reactor/Traits.hpp b/src/Reactor/Traits.hpp
index 4636c69..a33626b 100644
--- a/src/Reactor/Traits.hpp
+++ b/src/Reactor/Traits.hpp
@@ -86,14 +86,40 @@
 	// For T types that have a CToReactorT<> specialization,
 	// CToReactorPtrT<T>::type resolves to Pointer< CToReactorT<T> >, otherwise
 	// CToReactorPtrT<T>::type resolves to Pointer<Byte>.
-	template<typename T, typename ENABLE = void> struct CToReactorPtrT { using type = Pointer<Byte>; };
-	template<typename T> using CToReactorPtr = typename CToReactorPtrT<T>::type;
+	template<typename T, typename ENABLE = void> struct CToReactorPtrT
+	{
+		using type = Pointer<Byte>;
+		static inline type cast(const T* v); // implemented in Traits.inl
+	};
+
+	// CToReactorPtrT specialization for T types that have a CToReactorT<>
+	// specialization.
 	template<typename T> struct CToReactorPtrT<T, typename std::enable_if< IsDefined< CToReactorT<T> >::value>::type >
 	{
 		using type = Pointer< CToReactorT<T> >;
-		static inline type cast(T v); // implemented in Traits.inl
+		static inline type cast(const T* v); // implemented in Traits.inl
 	};
 
+	// CToReactorPtrT specialization for void*.
+	// Maps to Pointer<Byte> instead of Pointer<Void>.
+	template<> struct CToReactorPtrT<void, void>
+	{
+		using type = Pointer<Byte>;
+		static inline type cast(const void* v); // implemented in Traits.inl
+	};
+
+	// CToReactorPtr specialization for function pointer types.
+	// Maps to Pointer<Byte>.
+	// Drops the 'const' qualifier from the cast() method to avoid warnings
+	// about const having no meaning for function types.
+	template<typename T> struct CToReactorPtrT<T, typename std::enable_if< std::is_function<T>::value >::type >
+	{
+		using type = Pointer<Byte>;
+		static inline type cast(T* v); // implemented in Traits.inl
+	};
+
+	template<typename T> using CToReactorPtr = typename CToReactorPtrT<T>::type;
+
 	// CToReactor specialization for pointer types.
 	// For T types that have a CToReactorT<> specialization,
 	// CToReactorT<T*>::type resolves to Pointer< CToReactorT<T> >, otherwise
@@ -106,22 +132,6 @@
 		static inline type cast(T v); // implemented in Traits.inl
 	};
 
-	// CToReactor specialization for void*.
-	// Maps to Pointer<Byte> instead of Pointer<Void>.
-	template<> struct CToReactor<void*>
-	{
-		using type = Pointer<Byte>;
-		static type cast(void* v); // implemented in Reactor.cpp
-	};
-
-	// CToReactor specialization for void*.
-	// Maps to Pointer<Byte> instead of Pointer<Void>.
-	template<> struct CToReactor<const char*>
-	{
-		using type = Pointer<Byte>;
-		static type cast(const char* v); // implemented in Reactor.cpp
-	};
-
 	// CToReactor specialization for enum types.
 	template<typename T>
 	struct CToReactor<T, typename std::enable_if<std::is_enum<T>::value>::type>
diff --git a/src/Reactor/Traits.inl b/src/Reactor/Traits.inl
index 6654344..5cd46e3 100644
--- a/src/Reactor/Traits.inl
+++ b/src/Reactor/Traits.inl
@@ -17,25 +17,51 @@
 
 namespace rr
 {
+	// Non-specialized implementation of CToReactorPtrT::cast() defaults to
+	// returning a ConstantPointer for v.
+	template<typename T, typename ENABLE>
+	Pointer<Byte> CToReactorPtrT<T, ENABLE>::cast(const T* v)
+	{
+		return ConstantPointer(v);
+	}
+
+	// CToReactorPtrT specialization for T types that have a CToReactorT<>
+	// specialization.
 	template<typename T>
 	Pointer<CToReactorT<T>>
-	CToReactorPtrT<T, typename std::enable_if< IsDefined< CToReactorT<T> >::value>::type >::cast(T v)
+	CToReactorPtrT<T, typename std::enable_if< IsDefined< CToReactorT<T> >::value>::type >::cast(const T* v)
 	{
 		return type(v);
 	}
 
+	// CToReactorPtrT specialization for void*.
+	Pointer<Byte> CToReactorPtrT<void, void>::cast(const void* v)
+	{
+		return ConstantPointer(v);
+	}
+
+	// CToReactorPtrT specialization for function pointer types.
+	template<typename T>
+	Pointer<Byte>
+	CToReactorPtrT<T, typename std::enable_if< std::is_function<T>::value >::type>::cast(T* v)
+	{
+		return ConstantPointer(v);
+	}
+
+	// CToReactor specialization for pointer types.
 	template<typename T>
 	CToReactorPtr<typename std::remove_pointer<T>::type>
 	CToReactor<T, typename std::enable_if<std::is_pointer<T>::value>::type>::cast(T v)
 	{
-		return type(v);
+		return CToReactorPtrT<elem>::cast(v);
 	}
 
+	// CToReactor specialization for enum types.
 	template<typename T>
 	CToReactorT<typename std::underlying_type<T>::type>
 	CToReactor<T, typename std::enable_if<std::is_enum<T>::value>::type>::cast(T v)
 	{
-		return type(v);
+		return CToReactor<underlying>::cast(v);
 	}
 
 } // namespace rr