diff options
author | David Malcolm <dmalcolm@redhat.com> | 2015-01-12 22:25:37 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-01-12 22:25:37 +0000 |
commit | f6f2b01933268f73bf439ead94a1a72416a36cd5 (patch) | |
tree | d71d1bb61a2a2fc41e045a009e7486b70d2b7b9f /gcc/jit/libgccjit.c | |
parent | 16ba620346c945cddbd0ad49ef5c628e693cad33 (diff) | |
download | gcc-f6f2b01933268f73bf439ead94a1a72416a36cd5.zip gcc-f6f2b01933268f73bf439ead94a1a72416a36cd5.tar.gz gcc-f6f2b01933268f73bf439ead94a1a72416a36cd5.tar.bz2 |
libgccjit: detect various kinds of errors relating to params and locals
gcc/jit/ChangeLog:
* jit-recording.c (class gcc::jit::rvalue_usage_validator): New.
(gcc::jit::rvalue_usage_validator::rvalue_usage_validator): New
ctor.
(gcc::jit::rvalue_usage_validator::visit): New function.
(gcc::jit::recording::rvalue::verify_valid_within_stmt): New
function.
(gcc::jit::recording::rvalue::set_scope): New function.
(gcc::jit::recording::function::function): Call set_scope on each
param, issuing errors for any params that already have a function.
(gcc::jit::recording::block::add_eval): Return the new statement;
update the comment given that some error-checking now happens after
this returns.
(gcc::jit::recording::block::add_assignment): Likewise.
(gcc::jit::recording::block::add_assignment_op): Likewise.
(gcc::jit::recording::block::add_comment): Likewise.
(gcc::jit::recording::block::end_with_conditional): Likewise.
(gcc::jit::recording::block::end_with_jump): Likewise.
(gcc::jit::recording::block::end_with_return): Likewise.
(gcc::jit::recording::block::validate): Add a comment.
(gcc::jit::recording::unary_op::visit_children): New function.
(gcc::jit::recording::binary_op::visit_children): New function.
(gcc::jit::recording::comparison::visit_children): New function.
(gcc::jit::recording::cast::visit_children): New function.
(gcc::jit::recording::call::visit_children): New function.
(gcc::jit::recording::call_through_ptr::visit_children): New function.
(gcc::jit::recording::array_access::visit_children): New function.
(gcc::jit::recording::access_field_of_lvalue::visit_children): New
function.
(gcc::jit::recording::access_field_rvalue::visit_children): New
function.
(gcc::jit::recording::dereference_field_rvalue::visit_children):
New function.
(gcc::jit::recording::dereference_rvalue::visit_children): New
function.
(gcc::jit::recording::get_address_of_lvalue::visit_children): New
function.
* jit-recording.h: Within namespace gcc::jit::recording...
(class rvalue_visitor): New.
(rvalue::rvalue): Initialize m_scope.
(rvalue::get_loc): New accessor.
(rvalue::verify_valid_within_stmt): New function.
(rvalue::visit_children): New pure virtual function.
(rvalue::set_scope): New function.
(rvalue::get_scope): New function.
(rvalue::dyn_cast_param): New function.
(rvalue::m_scope): New field.
(param::visit_children): New empty function.
(param::dyn_cast_param): New function.
(function::get_loc): New function.
(block::add_eval): Return the new statement.
(block::add_assignment): Likewise.
(block::add_assignment_op): Likewise.
(block::add_comment): Likewise.
(block::end_with_conditional): Likewise.
(block::end_with_jump): Likewise.
(block::end_with_return): Likewise.
(global::visit_children): New function.
(memento_of_new_rvalue_from_const<HOST_TYPE>::visit_children):
New function.
(memento_of_new_string_literal::visit_children): New function.
(unary_op::visit_children): New function.
(binary_op::visit_children): New function.
(comparison::visit_children): New function.
(cast::visit_children): New function.
(call::visit_children): New function.
(call_through_ptr::visit_children): New function.
(array_access::visit_children): New function.
(access_field_of_lvalue::visit_children): New function.
(access_field_rvalue::visit_children): New function.
(dereference_field_rvalue::visit_children): New function.
(dereference_rvalue::visit_children): New function.
(get_address_of_lvalue::visit_children): New function.
(local::local): Call set_scope.
(local::visit_children): New function.
(statement::get_block): Make public.
* libgccjit.c (RETURN_VAL_IF_FAIL_PRINTF5): New macro.
(RETURN_NULL_IF_FAIL_PRINTF5): New macro.
(gcc_jit_context_new_function): Verify that each param has
not yet been used for creating another function.
(gcc_jit_block_add_eval): After creating the stmt, verify
that the rvalue expression tree is valid to use within it.
(gcc_jit_block_add_assignment): Likewise for the lvalue and
rvalue expression trees.
(gcc_jit_block_add_assignment_op): Likewise.
(gcc_jit_block_end_with_conditional): Likewise for the boolval
expression tree.
(gcc_jit_block_end_with_return): Likewise for the rvalue
expression tree.
(gcc_jit_block_end_with_void_return): Remove return of "void",
now that block::end_with_return is now non-void.
gcc/testsuite/ChangeLog:
* jit.dg/test-error-local-used-from-other-function.c: New test
case.
* jit.dg/test-error-param-reuse.c: New test case.
* jit.dg/test-error-param-sharing.c: New test case.
* jit.dg/test-error-param-used-from-other-function.c: New test
case.
* jit.dg/test-error-param-used-without-a-function.c: New test
case.
From-SVN: r219498
Diffstat (limited to 'gcc/jit/libgccjit.c')
-rw-r--r-- | gcc/jit/libgccjit.c | 83 |
1 files changed, 73 insertions, 10 deletions
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index d596d08..ad8ee75 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -172,6 +172,16 @@ struct gcc_jit_param : public gcc::jit::recording::param } \ JIT_END_STMT +#define RETURN_VAL_IF_FAIL_PRINTF5(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ + JIT_BEGIN_STMT \ + if (!(TEST_EXPR)) \ + { \ + jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \ + __func__, (A0), (A1), (A2), (A3), (A4)); \ + return (RETURN_EXPR); \ + } \ + JIT_END_STMT + #define RETURN_VAL_IF_FAIL_PRINTF6(TEST_EXPR, RETURN_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ JIT_BEGIN_STMT \ if (!(TEST_EXPR)) \ @@ -197,6 +207,9 @@ struct gcc_jit_param : public gcc::jit::recording::param #define RETURN_NULL_IF_FAIL_PRINTF4(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) \ RETURN_VAL_IF_FAIL_PRINTF4 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3) +#define RETURN_NULL_IF_FAIL_PRINTF5(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) \ + RETURN_VAL_IF_FAIL_PRINTF5 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4) + #define RETURN_NULL_IF_FAIL_PRINTF6(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) \ RETURN_VAL_IF_FAIL_PRINTF6 (TEST_EXPR, NULL, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, A4, A5) @@ -844,10 +857,23 @@ gcc_jit_context_new_function (gcc_jit_context *ctxt, ctxt, loc, "NULL params creating function %s", name); for (int i = 0; i < num_params; i++) - RETURN_NULL_IF_FAIL_PRINTF2 ( - params[i], - ctxt, loc, - "NULL parameter %i creating function %s", i, name); + { + RETURN_NULL_IF_FAIL_PRINTF2 ( + params[i], + ctxt, loc, + "NULL parameter %i creating function %s", i, name); + RETURN_NULL_IF_FAIL_PRINTF5 ( + (NULL == params[i]->get_scope ()), + ctxt, loc, + "parameter %i \"%s\"" + " (type: %s)" + " for function %s" + " was already used for function %s", + i, params[i]->get_debug_string (), + params[i]->get_type ()->get_debug_string (), + name, + params[i]->get_scope ()->get_debug_string ()); + } return (gcc_jit_function*) ctxt->new_function (loc, kind, return_type, name, @@ -1800,7 +1826,14 @@ gcc_jit_block_add_eval (gcc_jit_block *block, /* LOC can be NULL. */ RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); - return block->add_eval (loc, rvalue); + gcc::jit::recording::statement *stmt = block->add_eval (loc, rvalue); + + /* "stmt" should be good enough to be usable in error-messages, + but might still not be compilable; perform some more + error-checking here. We do this here so that the error messages + can contain a stringified version of "stmt", whilst appearing + as close as possible to the point of failure. */ + rvalue->verify_valid_within_stmt (__func__, stmt); } /* Public entrypoint. See description in libgccjit.h. @@ -1832,7 +1865,15 @@ gcc_jit_block_add_assignment (gcc_jit_block *block, rvalue->get_debug_string (), rvalue->get_type ()->get_debug_string ()); - return block->add_assignment (loc, lvalue, rvalue); + gcc::jit::recording::statement *stmt = block->add_assignment (loc, lvalue, rvalue); + + /* "stmt" should be good enough to be usable in error-messages, + but might still not be compilable; perform some more + error-checking here. We do this here so that the error messages + can contain a stringified version of "stmt", whilst appearing + as close as possible to the point of failure. */ + lvalue->verify_valid_within_stmt (__func__, stmt); + rvalue->verify_valid_within_stmt (__func__, stmt); } /* Public entrypoint. See description in libgccjit.h. @@ -1860,7 +1901,15 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block, op); RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue"); - return block->add_assignment_op (loc, lvalue, op, rvalue); + gcc::jit::recording::statement *stmt = block->add_assignment_op (loc, lvalue, op, rvalue); + + /* "stmt" should be good enough to be usable in error-messages, + but might still not be compilable; perform some more + error-checking here. We do this here so that the error messages + can contain a stringified version of "stmt", whilst appearing + as close as possible to the point of failure. */ + lvalue->verify_valid_within_stmt (__func__, stmt); + rvalue->verify_valid_within_stmt (__func__, stmt); } /* Internal helper function for determining if rvalue BOOLVAL is of @@ -1921,7 +1970,14 @@ gcc_jit_block_end_with_conditional (gcc_jit_block *block, on_false->get_debug_string (), on_false->get_function ()->get_debug_string ()); - return block->end_with_conditional (loc, boolval, on_true, on_false); + gcc::jit::recording::statement *stmt = block->end_with_conditional (loc, boolval, on_true, on_false); + + /* "stmt" should be good enough to be usable in error-messages, + but might still not be compilable; perform some more + error-checking here. We do this here so that the error messages + can contain a stringified version of "stmt", whilst appearing + as close as possible to the point of failure. */ + boolval->verify_valid_within_stmt (__func__, stmt); } /* Public entrypoint. See description in libgccjit.h. @@ -2003,7 +2059,14 @@ gcc_jit_block_end_with_return (gcc_jit_block *block, func->get_debug_string (), func->get_return_type ()->get_debug_string ()); - return block->end_with_return (loc, rvalue); + gcc::jit::recording::statement *stmt = block->end_with_return (loc, rvalue); + + /* "stmt" should be good enough to be usable in error-messages, + but might still not be compilable; perform some more + error-checking here. We do this here so that the error messages + can contain a stringified version of "stmt", whilst appearing + as close as possible to the point of failure. */ + rvalue->verify_valid_within_stmt (__func__, stmt); } /* Public entrypoint. See description in libgccjit.h. @@ -2029,7 +2092,7 @@ gcc_jit_block_end_with_void_return (gcc_jit_block *block, func->get_debug_string (), func->get_return_type ()->get_debug_string ()); - return block->end_with_return (loc, NULL); + block->end_with_return (loc, NULL); } /********************************************************************** |