@@ -1,5 +1,47 @@
2014-03-13 David Malcolm <dmalcolm@redhat.com>
+ * libgccjit.c (is_valid_cast): New.
+ (gcc_jit_context_new_cast): Check for compatible types.
+
+ * internal-api.c (gcc::jit::recording::memento_of_get_type::
+ is_int): New.
+ (gcc::jit::recording::memento_of_get_type::is_float): New.
+ (gcc::jit::recording::memento_of_get_type::is_bool): New.
+
+ * internal-api.h (gcc::jit::recording::type::is_int): New.
+ (gcc::jit::recording::type::is_float): New.
+ (gcc::jit::recording::type::is_bool): New.
+
+ (gcc::jit::recording::memento_of_get_type::is_int): New.
+ (gcc::jit::recording::memento_of_get_type::is_float): New.
+ (gcc::jit::recording::memento_of_get_type::is_bool): New.
+
+ (gcc::jit::recording::memento_of_get_pointer::is_int): New.
+ (gcc::jit::recording::memento_of_get_pointer::is_float): New.
+ (gcc::jit::recording::memento_of_get_pointer::is_bool): New.
+
+ (gcc::jit::recording::memento_of_get_const::is_int): New.
+ (gcc::jit::recording::memento_of_get_const::is_float): New.
+ (gcc::jit::recording::memento_of_get_const::is_bool): New.
+
+ (gcc::jit::recording::memento_of_get_volatile::is_int): New.
+ (gcc::jit::recording::memento_of_get_volatile::is_float): New.
+ (gcc::jit::recording::memento_of_get_volatile::is_bool): New.
+
+ (gcc::jit::recording::array_type::is_int): New.
+ (gcc::jit::recording::array_type::is_float): New.
+ (gcc::jit::recording::array_type::is_bool): New.
+
+ (gcc::jit::recording::function_type::is_int): New.
+ (gcc::jit::recording::function_type::is_float): New.
+ (gcc::jit::recording::function_type::is_bool): New.
+
+ (gcc::jit::recording::struct_::is_int): New.
+ (gcc::jit::recording::struct_::is_float): New.
+ (gcc::jit::recording::struct_::is_bool): New.
+
+2014-03-13 David Malcolm <dmalcolm@redhat.com>
+
* internal-api.c (gcc::jit::recording::context::set_str_option):
Provide NULL recording::location to add_error.
(gcc::jit::recording::context::set_int_option): Likewise.
@@ -856,6 +856,141 @@ recording::memento_of_get_type::dereference ()
}
}
+bool
+recording::memento_of_get_type::is_int () const
+{
+ switch (m_kind)
+ {
+ default: gcc_unreachable ();
+
+ case GCC_JIT_TYPE_VOID:
+ return false;
+
+ case GCC_JIT_TYPE_VOID_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_BOOL:
+ return false;
+
+ case GCC_JIT_TYPE_CHAR:
+ case GCC_JIT_TYPE_SIGNED_CHAR:
+ case GCC_JIT_TYPE_UNSIGNED_CHAR:
+ case GCC_JIT_TYPE_SHORT:
+ case GCC_JIT_TYPE_UNSIGNED_SHORT:
+ case GCC_JIT_TYPE_INT:
+ case GCC_JIT_TYPE_UNSIGNED_INT:
+ case GCC_JIT_TYPE_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG:
+ case GCC_JIT_TYPE_LONG_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ return true;
+
+ case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_DOUBLE:
+ case GCC_JIT_TYPE_LONG_DOUBLE:
+ return false;
+
+ case GCC_JIT_TYPE_CONST_CHAR_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_SIZE_T:
+ return true;
+
+ case GCC_JIT_TYPE_FILE_PTR:
+ return false;
+ }
+}
+
+bool
+recording::memento_of_get_type::is_float () const
+{
+ switch (m_kind)
+ {
+ default: gcc_unreachable ();
+
+ case GCC_JIT_TYPE_VOID:
+ return false;
+
+ case GCC_JIT_TYPE_VOID_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_BOOL:
+ return false;
+
+ case GCC_JIT_TYPE_CHAR:
+ case GCC_JIT_TYPE_SIGNED_CHAR:
+ case GCC_JIT_TYPE_UNSIGNED_CHAR:
+ case GCC_JIT_TYPE_SHORT:
+ case GCC_JIT_TYPE_UNSIGNED_SHORT:
+ case GCC_JIT_TYPE_INT:
+ case GCC_JIT_TYPE_UNSIGNED_INT:
+ case GCC_JIT_TYPE_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG:
+ case GCC_JIT_TYPE_LONG_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ return false;
+
+ case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_DOUBLE:
+ case GCC_JIT_TYPE_LONG_DOUBLE:
+ return true;
+
+ case GCC_JIT_TYPE_CONST_CHAR_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_SIZE_T:
+ return false;
+
+ case GCC_JIT_TYPE_FILE_PTR:
+ return false;
+ }
+}
+
+bool
+recording::memento_of_get_type::is_bool () const
+{
+ switch (m_kind)
+ {
+ default: gcc_unreachable ();
+
+ case GCC_JIT_TYPE_VOID:
+ return false;
+
+ case GCC_JIT_TYPE_VOID_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_BOOL:
+ return true;
+
+ case GCC_JIT_TYPE_CHAR:
+ case GCC_JIT_TYPE_SIGNED_CHAR:
+ case GCC_JIT_TYPE_UNSIGNED_CHAR:
+ case GCC_JIT_TYPE_SHORT:
+ case GCC_JIT_TYPE_UNSIGNED_SHORT:
+ case GCC_JIT_TYPE_INT:
+ case GCC_JIT_TYPE_UNSIGNED_INT:
+ case GCC_JIT_TYPE_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG:
+ case GCC_JIT_TYPE_LONG_LONG:
+ case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ return false;
+
+ case GCC_JIT_TYPE_FLOAT:
+ case GCC_JIT_TYPE_DOUBLE:
+ case GCC_JIT_TYPE_LONG_DOUBLE:
+ return false;
+
+ case GCC_JIT_TYPE_CONST_CHAR_PTR:
+ return false;
+
+ case GCC_JIT_TYPE_SIZE_T:
+ return false;
+
+ case GCC_JIT_TYPE_FILE_PTR:
+ return false;
+ }
+}
+
void
recording::memento_of_get_type::replay_into (replayer *r)
{
@@ -493,6 +493,9 @@ public:
return this;
}
+ virtual bool is_int () const = 0;
+ virtual bool is_float () const = 0;
+ virtual bool is_bool () const = 0;
playback::type *
playback_type ()
@@ -534,6 +537,10 @@ public:
return type::accepts_writes_from (rtype);
}
+ bool is_int () const;
+ bool is_float () const;
+ bool is_bool () const;
+
public:
void replay_into (replayer *r);
@@ -558,6 +565,10 @@ public:
void replay_into (replayer *r);
+ bool is_int () const { return false; }
+ bool is_float () const { return false; }
+ bool is_bool () const { return false; }
+
private:
string * make_debug_string ();
@@ -584,6 +595,10 @@ public:
/* Strip off the "const", giving the underlying type. */
type *unqualified () { return m_other_type; }
+ bool is_int () const { return m_other_type->is_int (); }
+ bool is_float () const { return m_other_type->is_float (); }
+ bool is_bool () const { return m_other_type->is_bool (); }
+
void replay_into (replayer *);
private:
@@ -606,6 +621,10 @@ public:
/* Strip off the "volatile", giving the underlying type. */
type *unqualified () { return m_other_type; }
+ bool is_int () const { return m_other_type->is_int (); }
+ bool is_float () const { return m_other_type->is_float (); }
+ bool is_bool () const { return m_other_type->is_bool (); }
+
void replay_into (replayer *);
private:
@@ -629,6 +648,11 @@ class array_type : public type
{}
type *dereference ();
+
+ bool is_int () const { return false; }
+ bool is_float () const { return false; }
+ bool is_bool () const { return false; }
+
void replay_into (replayer *);
private:
@@ -651,6 +675,11 @@ public:
type *dereference ();
function_type *as_a_function_type () { return this; }
+
+ bool is_int () const { return false; }
+ bool is_float () const { return false; }
+ bool is_bool () const { return false; }
+
void replay_into (replayer *);
type * get_return_type () const { return m_return_type; }
@@ -724,6 +753,10 @@ public:
type *dereference ();
+ bool is_int () const { return false; }
+ bool is_float () const { return false; }
+ bool is_bool () const { return false; }
+
void replay_into (replayer *r);
playback::struct_ *
@@ -882,6 +882,32 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
(gcc::jit::recording::rvalue **)args);
}
+static bool
+is_valid_cast (gcc::jit::recording::type *src_type,
+ gcc_jit_type *dst_type)
+{
+ bool src_is_int = src_type->is_int ();
+ bool dst_is_int = dst_type->is_int ();
+ bool src_is_float = src_type->is_float ();
+ bool dst_is_float = dst_type->is_float ();
+ bool src_is_bool = src_type->is_bool ();
+ bool dst_is_bool = dst_type->is_bool ();
+
+ if (src_is_int)
+ if (dst_is_int || dst_is_float || dst_is_bool)
+ return true;
+
+ if (src_is_float)
+ if (dst_is_int || dst_is_float)
+ return true;
+
+ if (src_is_bool)
+ if (dst_is_int || dst_is_bool)
+ return true;
+
+ return false;
+}
+
gcc_jit_rvalue *
gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_location *loc,
@@ -891,6 +917,13 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ RETURN_NULL_IF_FAIL_PRINTF3 (
+ is_valid_cast (rvalue->get_type (), type),
+ ctxt, loc,
+ "cannot cast %s from type: %s to type: %s",
+ rvalue->get_debug_string (),
+ rvalue->get_type ()->get_debug_string (),
+ type->get_debug_string ());
return static_cast <gcc_jit_rvalue *> (ctxt->new_cast (loc, rvalue, type));
}
@@ -1,3 +1,7 @@
+2014-03-13 David Malcolm <dmalcolm@redhat.com>
+
+ * jit.dg/test-error-bad-cast.c: New test case.
+
2014-03-11 David Malcolm <dmalcolm@redhat.com>
* jit.dg/harness.h (set_options): Increase optimization level from
new file mode 100644
@@ -0,0 +1,63 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ int
+ test_fn ()
+ {
+ struct foo f;
+ return (int)f;
+ }
+
+ and verify that the API complains about the bad cast.
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+
+ gcc_jit_struct *struct_foo =
+ gcc_jit_context_new_struct_type (ctxt, NULL, "foo",
+ 0, NULL);
+
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ int_type,
+ "test_fn",
+ 0, NULL,
+ 0);
+ gcc_jit_lvalue *f =
+ gcc_jit_function_new_local (
+ test_fn,
+ NULL,
+ gcc_jit_struct_as_type (struct_foo), "f");
+
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+
+ gcc_jit_block_end_with_return (
+ block, NULL,
+ gcc_jit_context_new_cast (ctxt, NULL,
+ gcc_jit_lvalue_as_rvalue (f),
+ int_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+
+ /* Verify that the correct error message was emitted. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ "gcc_jit_context_new_cast:"
+ " cannot cast f from type: struct foo"
+ " to type: int");
+}
+