+2019-07-04 Andrea Corallo <andrea.corallo@arm.com>
+
+ * docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag.
+ * docs/topics/types.rst: Add gcc_jit_context_new_bitfield.
+ * jit-common.h (namespace recording): Add class bitfield.
+ * jit-playback.c:
+ (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): Add macros.
+ (playback::context::new_bitfield): New method.
+ (playback::compound_type::set_fields): Add bitfield support.
+ (playback::lvalue::mark_addressable): Was jit_mark_addressable make this
+ a method of lvalue plus return a bool to communicate success.
+ (playback::lvalue::get_address): Check for jit_mark_addressable return
+ value.
+ * jit-playback.h (new_bitfield): New method.
+ (class bitfield): New class.
+ (class lvalue): Add jit_mark_addressable method.
+ * jit-recording.c (recording::context::new_bitfield): New method.
+ (recording::bitfield::replay_into): New method.
+ (recording::bitfield::write_to_dump): Likewise.
+ (recording::bitfield::make_debug_string): Likewise.
+ (recording::bitfield::write_reproducer): Likewise.
+ * jit-recording.h (class context): Add new_bitfield method.
+ (class field): Make it derivable by class bitfield.
+ (class bitfield): Add new class.
+ * libgccjit++.h (class context): Add new_bitfield method.
+ * libgccjit.c (struct gcc_jit_bitfield): New structure.
+ (gcc_jit_context_new_bitfield): New function.
+ * libgccjit.h
+ (LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield) New macro.
+ (gcc_jit_context_new_bitfield): New function.
+ * libgccjit.map (LIBGCCJIT_ABI_12) New ABI tag.
+
2019-03-21 Jakub Jelinek <jakub@redhat.com>
* jit-recording.c (reproducer::m_set_identifiers): Use false as Lazy
--------------------
``LIBGCCJIT_ABI_11`` covers the addition of
:func:`gcc_jit_context_add_driver_option`
+
+``LIBGCCJIT_ABI_12``
+--------------------
+``LIBGCCJIT_ABI_12`` covers the addition of
+:func:`gcc_jit_context_new_bitfield`
underlying string, so it is valid to pass in a pointer to an on-stack
buffer.
+.. function:: gcc_jit_field *\
+ gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,\
+ gcc_jit_location *loc,\
+ gcc_jit_type *type,\
+ int width,\
+ const char *name)
+
+ Construct a new bit field, with the given type width and name.
+
+ The parameter ``name`` must be non-NULL. The call takes a copy of the
+ underlying string, so it is valid to pass in a pointer to an on-stack
+ buffer.
+
+ The parameter ``type`` must be an integer type.
+
+ The parameter ``width`` must be a positive integer that does not exceed the
+ size of ``type``.
+
+ This API entrypoint was added in :ref:`LIBGCCJIT_ABI_12`; you can test
+ for its presence using
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+
.. function:: gcc_jit_object *\
gcc_jit_field_as_object (gcc_jit_field *field)
class union_;
class vector_type;
class field;
+ class bitfield;
class fields;
class function;
class block;
#include "jit-builtins.h"
#include "jit-tempdir.h"
+/* Compare with gcc/c-family/c-common.h: DECL_C_BIT_FIELD,
+ SET_DECL_C_BIT_FIELD.
+ These are redefined here to avoid depending from the C frontend. */
+#define DECL_JIT_BIT_FIELD(NODE) \
+ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
+#define SET_DECL_JIT_BIT_FIELD(NODE) \
+ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
/* gcc::jit::playback::context::build_cast uses the convert.h API,
which in turn requires the frontend to provide a "convert"
return new field (decl);
}
+/* Construct a playback::bitfield instance (wrapping a tree). */
+
+playback::field *
+playback::context::
+new_bitfield (location *loc,
+ type *type,
+ int width,
+ const char *name)
+{
+ gcc_assert (type);
+ gcc_assert (name);
+ gcc_assert (width);
+
+ /* compare with c/c-decl.c:grokfield, grokdeclarator and
+ check_bitfield_type_and_width. */
+
+ tree tree_type = type->as_tree ();
+ gcc_assert (INTEGRAL_TYPE_P (tree_type));
+ tree tree_width = build_int_cst (integer_type_node, width);
+ if (compare_tree_int (tree_width, TYPE_PRECISION (tree_type)) > 0)
+ {
+ add_error (
+ loc,
+ "width of bit-field %s (width: %i) is wider than its type (width: %i)",
+ name, width, TYPE_PRECISION (tree_type));
+ return NULL;
+ }
+
+ tree decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+ get_identifier (name), type->as_tree ());
+ DECL_NONADDRESSABLE_P (decl) = true;
+ DECL_INITIAL (decl) = tree_width;
+ SET_DECL_JIT_BIT_FIELD (decl);
+
+ if (loc)
+ set_tree_location (decl, loc);
+
+ return new field (decl);
+}
+
/* Construct a playback::compound_type instance (wrapping a tree). */
playback::compound_type *
for (unsigned i = 0; i < fields->length (); i++)
{
field *f = (*fields)[i];
- DECL_CONTEXT (f->as_tree ()) = t;
- fieldlist = chainon (f->as_tree (), fieldlist);
+ tree x = f->as_tree ();
+ DECL_CONTEXT (x) = t;
+ if (DECL_JIT_BIT_FIELD (x))
+ {
+ unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
+ DECL_SIZE (x) = bitsize_int (width);
+ DECL_BIT_FIELD (x) = 1;
+ }
+ fieldlist = chainon (x, fieldlist);
}
fieldlist = nreverse (fieldlist);
TYPE_FIELDS (t) = fieldlist;
return new lvalue (get_context (), datum);
}
-/* Mark EXP saying that we need to be able to take the
+/* Mark the lvalue saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Compare with e.g. c/c-typeck.c: c_mark_addressable. */
+ Compare with e.g. c/c-typeck.c: c_mark_addressable really_atomic_lvalue.
+ Returns false if a failure occurred (an error will already have been
+ added to the active context for this case). */
-static void
-jit_mark_addressable (tree exp)
+bool
+playback::lvalue::
+mark_addressable (location *loc)
{
- tree x = exp;
+ tree x = as_tree ();;
while (1)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
- /* (we don't yet support bitfields) */
+ if (DECL_JIT_BIT_FIELD (TREE_OPERAND (x, 1)))
+ {
+ gcc_assert (gcc::jit::active_playback_ctxt);
+ gcc::jit::
+ active_playback_ctxt->add_error (loc,
+ "cannot take address of "
+ "bit-field");
+ return false;
+ }
/* fallthrough */
case ADDR_EXPR:
case ARRAY_REF:
case COMPOUND_LITERAL_EXPR:
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return;
+ return true;
case VAR_DECL:
case CONST_DECL:
TREE_ADDRESSABLE (x) = 1;
/* fallthrough */
default:
- return;
+ return true;
}
}
tree ptr = build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
if (loc)
get_context ()->set_tree_location (ptr, loc);
- jit_mark_addressable (t_lvalue);
- return new rvalue (get_context (), ptr);
+ if (mark_addressable (loc))
+ return new rvalue (get_context (), ptr);
+ else
+ return NULL;
}
/* The wrapper subclasses are GC-managed, but can own non-GC memory.
type *type,
const char *name);
+ field *
+ new_bitfield (location *loc,
+ type *type,
+ int width,
+ const char *name);
+
compound_type *
new_compound_type (location *loc,
const char *name,
tree m_inner;
};
+class bitfield : public field {};
+
class function : public wrapper
{
public:
rvalue *
get_address (location *loc);
+private:
+ bool mark_addressable (location *loc);
};
class param : public lvalue
} // namespace gcc
#endif /* JIT_PLAYBACK_H */
-
return result;
}
+/* Create a recording::bitfield instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitfield. */
+
+recording::field *
+recording::context::new_bitfield (recording::location *loc,
+ recording::type *type,
+ int width,
+ const char *name)
+{
+ recording::field *result =
+ new recording::bitfield (this, loc, type, width, new_string (name));
+ record (result);
+ return result;
+}
+
/* Create a recording::struct_ instance and add it to this context's
list of mementos and list of compound types.
recording::memento::write_to_dump. Dump each field
by dumping a line of the form:
TYPE NAME;
- so that we can build up a struct/union field-byfield. */
+ so that we can build up a struct/union field by field. */
void
recording::field::write_to_dump (dump &d)
m_name->get_debug_string ());
}
+/* The implementation of class gcc::jit::recording::bitfield. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitfield. */
+
+void
+recording::bitfield::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
+ m_type->playback_type (),
+ m_width,
+ playback_string (m_name)));
+}
+
+/* Override the default implementation of
+ recording::memento::write_to_dump. Dump each bit field
+ by dumping a line of the form:
+ TYPE NAME:WIDTH;
+ so that we can build up a struct/union field by field. */
+
+void
+recording::bitfield::write_to_dump (dump &d)
+{
+ d.write (" %s %s:%d;\n",
+ m_type->get_debug_string (),
+ m_name->c_str (),
+ m_width);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ results of new_bitfield. */
+
+recording::string *
+recording::bitfield::make_debug_string ()
+{
+ return string::from_printf (m_ctxt,
+ "%s:%d",
+ m_name->c_str (), m_width);
+}
+
+/* Implementation of recording::memento::write_reproducer for bitfields. */
+
+void
+recording::bitfield::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "bitfield");
+ r.write (" gcc_jit_field *%s =\n"
+ " gcc_jit_context_new_bitfield (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_type *type, */\n"
+ " %d, /* int width, */\n"
+ " %s); /* const char *name */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_type (m_type),
+ m_width,
+ m_name->get_debug_string ());
+}
+
/* The implementation of class gcc::jit::recording::compound_type */
/* The constructor for gcc::jit::recording::compound_type. */
type *type,
const char *name);
+ field *
+ new_bitfield (location *loc,
+ type *type,
+ int width,
+ const char *name);
+
struct_ *
new_struct_type (location *loc,
const char *name);
compound_type * get_container () const { return m_container; }
void set_container (compound_type *c) { m_container = c; }
- void replay_into (replayer *) FINAL OVERRIDE;
+ void replay_into (replayer *) OVERRIDE;
- void write_to_dump (dump &d) FINAL OVERRIDE;
+ void write_to_dump (dump &d) OVERRIDE;
playback::field *
playback_field () const
}
private:
- string * make_debug_string () FINAL OVERRIDE;
- void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ string * make_debug_string () OVERRIDE;
+ void write_reproducer (reproducer &r) OVERRIDE;
-private:
+protected:
location *m_loc;
type *m_type;
string *m_name;
compound_type *m_container;
};
+
+class bitfield : public field
+{
+public:
+ bitfield (context *ctxt,
+ location *loc,
+ type *type,
+ int width,
+ string *name)
+ : field (ctxt, loc, type, name),
+ m_width (width)
+ {}
+
+ void replay_into (replayer *) FINAL OVERRIDE;
+
+ void write_to_dump (dump &d) FINAL OVERRIDE;
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+ int m_width;
+};
+
/* Base class for struct_ and union_ */
class compound_type : public type
{
field new_field (type type_, const std::string &name,
location loc = location ());
+ field new_bitfield (type type_, int width, const std::string &name,
+ location loc = location ());
+
struct_ new_struct_type (const std::string &name,
std::vector<field> &fields,
location loc = location ());
name.c_str ()));
}
+inline field
+context::new_bitfield (type type_, int width, const std::string &name,
+ location loc)
+{
+ return field (gcc_jit_context_new_bitfield (m_inner_ctxt,
+ loc.get_inner_location (),
+ type_.get_inner_type (),
+ width,
+ name.c_str ()));
+}
+
inline struct_
context::new_struct_type (const std::string &name,
std::vector<field> &fields,
{
};
+struct gcc_jit_bitfield : public gcc::jit::recording::bitfield
+{
+};
+
struct gcc_jit_function : public gcc::jit::recording::function
{
};
return (gcc_jit_field *)ctxt->new_field (loc, type, name);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitfield method, in
+ jit-recording.c. */
+
+gcc_jit_field *
+gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *type,
+ int width,
+ const char *name)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ RETURN_NULL_IF_FAIL_PRINTF2 (type->is_int () || type->is_bool (),
+ ctxt, loc,
+ "bit-field %s has non integral type %s",
+ name, type->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ width > 0, ctxt, loc,
+ "invalid width %d for bitfield \"%s\" (must be > 0)",
+ width, name);
+ RETURN_NULL_IF_FAIL_PRINTF2 (
+ type->has_known_size (),
+ ctxt, loc,
+ "unknown size for field \"%s\" (type: %s)",
+ name,
+ type->get_debug_string ());
+
+ return (gcc_jit_field *)ctxt->new_bitfield (loc, type, width, name);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this calls the trivial
gcc_jit_type *type,
const char *name);
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+
+/* Create a bit field, for use within a struct or union.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_12; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+*/
+extern gcc_jit_field *
+gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *type,
+ int width,
+ const char *name);
+
/* Upcasting from field to object. */
extern gcc_jit_object *
gcc_jit_field_as_object (gcc_jit_field *field);
LIBGCCJIT_ABI_11 {
global:
gcc_jit_context_add_driver_option;
-} LIBGCCJIT_ABI_10;
\ No newline at end of file
+} LIBGCCJIT_ABI_10;
+
+LIBGCCJIT_ABI_12 {
+ global:
+ gcc_jit_context_new_bitfield;
+} LIBGCCJIT_ABI_11;
\ No newline at end of file
+2019-07-04 Andrea Corallo <andrea.corallo@arm.com>
+
+ * jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c.
+ * jit.dg/test-accessing-bitfield.c: New testcase.
+ * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c:
+ Likewise.
+ * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c:
+ Likewise.
+ * jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c:
+ Likewise.
+
2019-07-04 Jan Hubicka <jh@suse.cz>
* gcc.dg/tree-ssa/alias-access-path-3.c: New testcase.
PR tree-optimization/91033
* gcc.target/i386/pr91033.c: New test.
-
+
2019-07-03 Bob Duff <duff@adacore.com>
* gnat.dg/task2.adb, gnat.dg/task2_pkg.adb,
hooks provided by each test case. */
#define COMBINED_TEST
+/* test-accessing-bitfield.c */
+#define create_code create_code_accessing_bitfield
+#define verify_code verify_code_accessing_bitfield
+#include "test-accessing-bitfield.c"
+#undef create_code
+#undef verify_code
+
/* test-accessing-struct.c */
#define create_code create_code_accessing_struct
#define verify_code verify_code_accessing_struct
};
const struct testcase testcases[] = {
+ {"accessing_bitfield",
+ create_code_accessing_bitfield,
+ verify_code_accessing_bitfield},
{"accessing_struct",
create_code_accessing_struct,
verify_code_accessing_struct},
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+struct bit_foo
+{
+ int i:3;
+ int x:5;
+ int y:5;
+ int z:10;
+ int j:3;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ void
+ test_bitfield_access (struct bit_foo *f)
+ {
+ f->z = f->x + f->y;
+ }
+ */
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_field *i =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 3,
+ "i");
+ gcc_jit_field *x =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 5,
+ "x");
+ gcc_jit_field *y =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 5,
+ "y");
+ gcc_jit_field *z =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 10,
+ "z");
+ gcc_jit_field *j =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 3,
+ "j");
+ gcc_jit_field *fields[] = {i, x, y, z, j};
+ gcc_jit_struct *struct_type =
+ gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 5, fields);
+ gcc_jit_type *ptr_type =
+ gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
+
+ /* Build the test function. */
+ gcc_jit_param *param_f =
+ gcc_jit_context_new_param (ctxt, NULL, ptr_type, "f");
+ gcc_jit_function *test_fn =
+ gcc_jit_context_new_function (ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ void_type,
+ "test_bitfield_access",
+ 1, ¶m_f,
+ 0);
+
+ /* f->x + f->y */
+ gcc_jit_rvalue *sum =
+ gcc_jit_context_new_binary_op (
+ ctxt, NULL,
+ GCC_JIT_BINARY_OP_PLUS,
+ int_type,
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_f),
+ NULL,
+ x)),
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_f),
+ NULL,
+ y)));
+
+ /* f->z = ... */
+ gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+ gcc_jit_block_add_assignment (
+ block,
+ NULL,
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_f),
+ NULL,
+ z),
+ sum);
+ gcc_jit_block_end_with_void_return (block, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef void (*fn_type) (struct bit_foo *);
+ CHECK_NON_NULL (result);
+
+ fn_type test_bitfield_access =
+ (fn_type)gcc_jit_result_get_code (result, "test_bitfield_access");
+ CHECK_NON_NULL (test_bitfield_access);
+
+ struct bit_foo tmp;
+ tmp.i = 3;
+ tmp.x = 5;
+ tmp.y = 7;
+ tmp.z = 0;
+ tmp.j = 3;
+
+ /* Call the JIT-generated function. */
+ test_bitfield_access (&tmp);
+
+ /* Verify that the code correctly modified the field "z". */
+ CHECK_VALUE (tmp.z, 12);
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to declare a bit-field with invalid type. */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ gcc_jit_type *bool_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *long_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG);
+ gcc_jit_type *float_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ bool_type,
+ 3,
+ "b");
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 3,
+ "i");
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ long_type,
+ 3,
+ "l");
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ float_type,
+ 5,
+ "f");
+}
+
+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_bitfield: bit-field f has non "
+ "integral type float");
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to declare a bit-field with invalid width. */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ gcc_jit_type *short_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SHORT);
+ gcc_jit_field *i =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ short_type,
+ 3,
+ "i");
+ gcc_jit_field *j =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ short_type,
+ 157,
+ "j");
+ gcc_jit_field *fields[] = {i, j};
+ gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ CHECK_VALUE (result, NULL);
+ char error_str[256];
+ snprintf (error_str, sizeof (error_str),
+ "width of bit-field j (width: 157) is wider than its type "
+ "(width: %zu)", 8 * sizeof (short));
+
+ /* Verify that the correct error message was emitted. */
+
+ CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+ error_str);
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to dereference a bit-field. */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ struct bit_foo
+ {
+ int i:3;
+ int j:3;
+ };
+
+ struct bit_foo f;
+ &(f.j)
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_field *i =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 3,
+ "i");
+ gcc_jit_field *j =
+ gcc_jit_context_new_bitfield (ctxt,
+ NULL,
+ int_type,
+ 3,
+ "j");
+ gcc_jit_field *fields[] = {i, j};
+ gcc_jit_type *struct_type =
+ gcc_jit_struct_as_type (
+ gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields));
+
+ gcc_jit_lvalue *f_struct =
+ gcc_jit_context_new_global (ctxt,
+ NULL,
+ GCC_JIT_GLOBAL_INTERNAL,
+ struct_type,
+ "f");
+
+ gcc_jit_lvalue_get_address (
+ gcc_jit_lvalue_access_field (
+ f_struct,
+ NULL,
+ j),
+ NULL);
+}
+
+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),
+ "cannot take address of bit-field");
+}