jit: gcc diagnostics are jit errors

libgccjit performs numerous checks at the API boundary, but
if these succeed, it ignores errors and other diagnostics emitted
within the core of gcc, and treats the compile of a gcc_jit_context
as having succeeded.

This patch ensures that if any diagnostics are emitted, they
are visible from the libgccjit API, and that the the context is
flagged as having failed.

For now any kind of diagnostic is treated as a jit error,
so warnings and notes also count as errors.

gcc/jit/ChangeLog:
	* dummy-frontend.c: Include diagnostic.h.
	(jit_begin_diagnostic): New function.
	(jit_end_diagnostic): New function.
	(jit_langhook_init): Register jit_begin_diagnostic
	and jit_end_diagnostic with the global_dc.
	* jit-playback.c: Include diagnostic.h.
	(gcc::jit::playback::context::add_diagnostic): New method.
	* jit-playback.h (struct diagnostic_context): Add forward
	declaration.
	(gcc::jit::playback::context::add_diagnostic): New method.

gcc/testsuite/ChangeLog:
	* jit.dg/test-error-array-bounds.c: New test case.

From-SVN: r236342
This commit is contained in:
David Malcolm 2016-05-17 19:28:47 +00:00 committed by David Malcolm
parent f51703a8f8
commit 6b5423a512
6 changed files with 168 additions and 0 deletions

View File

@ -1,3 +1,16 @@
2016-05-17 David Malcolm <dmalcolm@redhat.com>
* dummy-frontend.c: Include diagnostic.h.
(jit_begin_diagnostic): New function.
(jit_end_diagnostic): New function.
(jit_langhook_init): Register jit_begin_diagnostic
and jit_end_diagnostic with the global_dc.
* jit-playback.c: Include diagnostic.h.
(gcc::jit::playback::context::add_diagnostic): New method.
* jit-playback.h (struct diagnostic_context): Add forward
declaration.
(gcc::jit::playback::context::add_diagnostic): New method.
2016-05-17 David Malcolm <dmalcolm@redhat.com>
* docs/topics/expressions.rst (Function calls): Document

View File

@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "diagnostic.h"
#include <mpfr.h>
@ -90,6 +91,35 @@ struct ggc_root_tab jit_root_tab[] =
LAST_GGC_ROOT_TAB
};
/* JIT-specific implementation of diagnostic callbacks. */
/* Implementation of "begin_diagnostic". */
static void
jit_begin_diagnostic (diagnostic_context */*context*/,
diagnostic_info */*diagnostic*/)
{
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
/* No-op (apart from logging); the real error-handling is done in the
"end_diagnostic" hook. */
}
/* Implementation of "end_diagnostic". */
static void
jit_end_diagnostic (diagnostic_context *context,
diagnostic_info *diagnostic)
{
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
/* Delegate to the playback context (and thence to the
recording context). */
gcc::jit::active_playback_ctxt->add_diagnostic (context, diagnostic);
}
/* Language hooks. */
static bool
@ -105,6 +135,10 @@ jit_langhook_init (void)
registered_root_tab = true;
}
gcc_assert (global_dc);
global_dc->begin_diagnostic = jit_begin_diagnostic;
global_dc->end_diagnostic = jit_end_diagnostic;
build_common_tree_nodes (false);
/* I don't know why this has to be done explicitly. */

View File

@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h"
#include "fold-const.h"
#include "gcc.h"
#include "diagnostic.h"
#include <pthread.h>
@ -2833,6 +2834,43 @@ add_error_va (location *loc, const char *fmt, va_list ap)
fmt, ap);
}
/* Report a diagnostic up to the jit context as an error,
so that the compilation is treated as a failure.
For now, any kind of diagnostic is treated as an error by the jit
API. */
void
playback::context::
add_diagnostic (struct diagnostic_context *diag_context,
struct diagnostic_info *diagnostic)
{
/* At this point the text has been formatted into the pretty-printer's
output buffer. */
pretty_printer *pp = diag_context->printer;
const char *text = pp_formatted_text (pp);
/* Get location information (if any) from the diagnostic.
The recording::context::add_error[_va] methods require a
recording::location. We can't lookup the playback::location
from the file/line/column since any playback location instances
may have been garbage-collected away by now, so instead we create
another recording::location directly. */
location_t gcc_loc = diagnostic_location (diagnostic);
recording::location *rec_loc = NULL;
if (gcc_loc)
{
expanded_location exploc = expand_location (gcc_loc);
if (exploc.file)
rec_loc = m_recording_ctxt->new_location (exploc.file,
exploc.line,
exploc.column,
false);
}
m_recording_ctxt->add_error (rec_loc, "%s", text);
pp_clear_output_area (pp);
}
/* Dealing with the linemap API. */
/* Construct a playback::location for a recording::location, if it

View File

@ -27,6 +27,9 @@ along with GCC; see the file COPYING3. If not see
#include "jit-recording.h"
struct diagnostic_context;
struct diagnostic_info;
namespace gcc {
namespace jit {
@ -202,6 +205,10 @@ public:
const char *
get_first_error () const;
void
add_diagnostic (struct diagnostic_context *context,
struct diagnostic_info *diagnostic);
void
set_tree_location (tree t, location *loc);

View File

@ -1,3 +1,7 @@
2016-05-17 David Malcolm <dmalcolm@redhat.com>
* jit.dg/test-error-array-bounds.c: New test case.
2016-05-17 Marc Glisse <marc.glisse@inria.fr>
* gcc.dg/tree-ssa/and-1.c: New testcase.

View File

@ -0,0 +1,72 @@
#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:
char
test_array_bounds (void)
{
char buffer[10];
return buffer[10];
}
with -Warray-bounds and -ftree-vrp and verify that the
out-of-bounds access is detected and reported as a jit error. */
gcc_jit_context_add_command_line_option (ctxt, "-Warray-bounds");
gcc_jit_context_add_command_line_option (ctxt, "-ftree-vrp");
/* Ensure that the error message doesn't contain colorization codes,
even if run at a TTY. */
gcc_jit_context_add_command_line_option (ctxt, "-fdiagnostics-color=never");
gcc_jit_type *char_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
gcc_jit_type *array_type =
gcc_jit_context_new_array_type (ctxt, NULL,
char_type, 10);
gcc_jit_type *int_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
/* Build the test_fn. */
gcc_jit_function *test_fn =
gcc_jit_context_new_function (ctxt, NULL,
GCC_JIT_FUNCTION_EXPORTED,
char_type,
"test_array_bounds",
0, NULL,
0);
gcc_jit_lvalue *buffer =
gcc_jit_function_new_local (test_fn, NULL, array_type, "buffer");
/* tree-vrp.c:check_all_array_refs only checks array lookups that
have source locations. */
gcc_jit_location *dummy_loc =
gcc_jit_context_new_location (ctxt, "dummy.c", 10, 4);
gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
gcc_jit_rvalue *index =
gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 10);
gcc_jit_lvalue *read_of_the_buffer =
gcc_jit_context_new_array_access (ctxt, dummy_loc,
gcc_jit_lvalue_as_rvalue (buffer),
index);
gcc_jit_block_end_with_return (
block, dummy_loc,
gcc_jit_lvalue_as_rvalue (read_of_the_buffer));
}
void
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
{
/* Verify that the diagnostic led to the context failing... */
CHECK_VALUE (result, NULL);
/* ...and that the message was captured by the API. */
CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
"array subscript is above array bounds [-Warray-bounds]");
}