@@ -123,7 +123,9 @@ In general, if an error occurs when using an API entrypoint, the
entrypoint returns NULL. You don't have to check everywhere for NULL
results, since the API handles a NULL being passed in for any
argument by issuing another error. This typically leads to a cascade of
-followup error messages, but is safe (albeit verbose).
+followup error messages, but is safe (albeit verbose). The first error
+message is usually the one to pay attention to, since it is likely to
+be responsible for all of the rest:
.. function:: const char *\
gcc_jit_context_get_first_error (gcc_jit_context *ctxt)
@@ -135,6 +137,20 @@ followup error messages, but is safe (albeit verbose).
If no errors occurred, this will be NULL.
+If you are wrapping the C API for a higher-level language that supports
+exception-handling, you may instead by interested in the last error that
+occurred on the context, so that you can embed this in an exception:
+
+.. function:: const char *\
+ gcc_jit_context_get_last_error (gcc_jit_context *ctxt)
+
+ Returns the last error message that occurred on the context.
+
+ The returned string is valid for the rest of the lifetime of the
+ context.
+
+ If no errors occurred, this will be NULL.
+
Debugging
---------
@@ -175,6 +175,8 @@ recording::context::context (context *parent_ctxt)
m_error_count (0),
m_first_error_str (NULL),
m_owns_first_error_str (false),
+ m_last_error_str (NULL),
+ m_owns_last_error_str (false),
m_mementos (),
m_compound_types (),
m_functions (),
@@ -230,6 +232,10 @@ recording::context::~context ()
if (m_owns_first_error_str)
free (m_first_error_str);
+
+ if (m_owns_last_error_str)
+ if (m_last_error_str != m_first_error_str)
+ free (m_last_error_str);
}
/* Add the given mememto to the list of those tracked by this
@@ -984,9 +990,12 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
m_first_error_str = const_cast <char *> (errmsg);
m_owns_first_error_str = has_ownership;
}
- else
- if (has_ownership)
- free (malloced_msg);
+
+ if (m_owns_last_error_str)
+ if (m_last_error_str != m_first_error_str)
+ free (m_last_error_str);
+ m_last_error_str = const_cast <char *> (errmsg);
+ m_owns_last_error_str = has_ownership;
m_error_count++;
}
@@ -1003,6 +1012,18 @@ recording::context::get_first_error () const
return m_first_error_str;
}
+/* Get the message for the last error that occurred on this context, or
+ NULL if no errors have occurred on it.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_last_error. */
+
+const char *
+recording::context::get_last_error () const
+{
+ return m_last_error_str;
+}
+
/* Lazily generate and record a recording::type representing an opaque
struct named "FILE".
@@ -235,6 +235,9 @@ public:
const char *
get_first_error () const;
+ const char *
+ get_last_error () const;
+
bool errors_occurred () const
{
if (m_parent_ctxt)
@@ -261,6 +264,9 @@ private:
char *m_first_error_str;
bool m_owns_first_error_str;
+ char *m_last_error_str;
+ bool m_owns_last_error_str;
+
char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
@@ -2164,6 +2164,20 @@ gcc_jit_context_get_first_error (gcc_jit_context *ctxt)
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
+ gcc::jit::recording::context::get_last_error method in
+ jit-recording.c. */
+
+const char *
+gcc_jit_context_get_last_error (gcc_jit_context *ctxt)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+
+ return ctxt->get_last_error ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
gcc::jit::result::get_code method in jit-result.c. */
void *
@@ -279,6 +279,16 @@ gcc_jit_context_set_logfile (gcc_jit_context *ctxt,
extern const char *
gcc_jit_context_get_first_error (gcc_jit_context *ctxt);
+/* To be called after a compile, this gives the last error message
+ that occurred on the context.
+
+ The returned string is valid for the rest of the lifetime of the
+ context.
+
+ If no errors occurred, this will be NULL. */
+extern const char *
+gcc_jit_context_get_last_error (gcc_jit_context *ctxt);
+
/* Locate a given function within the built machine code.
This will need to be cast to a function pointer of the
correct type before it can be called. */
@@ -36,6 +36,7 @@
gcc_jit_context_enable_dump;
gcc_jit_context_get_builtin_function;
gcc_jit_context_get_first_error;
+ gcc_jit_context_get_last_error;
gcc_jit_context_get_type;
gcc_jit_context_get_int_type;
gcc_jit_context_new_array_access;
@@ -62,4 +62,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
" source block initial is in function test_fn"
" whereas target block block_within_other_fn"
" is in function other_fn");
+ /* Example of a testcase in which the last error != first error. */
+ CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+ "unterminated block in other_fn: block_within_other_fn");
}
@@ -27,5 +27,7 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
/* Verify that the correct error message was emitted. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
"gcc_jit_context_new_function: NULL return_type");
+ CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt),
+ "gcc_jit_context_new_function: NULL return_type");
}