Committed to dmalcolm/jit: gcc/jit/ * internal-api (gcc::jit::recording::context::new_call): Verify the argument count of the call against the parameter count of the function, issuing an error if there's a mismatch.
* internal-api.h (gcc::jit::recording::function::get_name): New. * (gcc::jit::recording::function::get_params): New. * (gcc::jit::recording::function::is_variadic): New. gcc/testsuite/ * jit.dg/test-error-call-with-not-enough-args.c: New test case. * jit.dg/test-error-call-with-too-many-args.c: New test case. * jit.dg/test-null-passed-to-api.c: Rename to... * jit.dg/test-error-null-passed-to-api.c: ...this, so that error-handling test cases are consistently named. --- gcc/jit/internal-api.c | 20 +++++ gcc/jit/internal-api.h | 4 + .../jit.dg/test-error-call-with-not-enough-args.c | 86 +++++++++++++++++++++ .../jit.dg/test-error-call-with-too-many-args.c | 88 ++++++++++++++++++++++ .../jit.dg/test-error-null-passed-to-api.c | 31 ++++++++ gcc/testsuite/jit.dg/test-null-passed-to-api.c | 31 -------- 6 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-error-call-with-not-enough-args.c create mode 100644 gcc/testsuite/jit.dg/test-error-call-with-too-many-args.c create mode 100644 gcc/testsuite/jit.dg/test-error-null-passed-to-api.c delete mode 100644 gcc/testsuite/jit.dg/test-null-passed-to-api.c diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c index 64a0912..cf9195d0 100644 --- a/gcc/jit/internal-api.c +++ b/gcc/jit/internal-api.c @@ -278,6 +278,26 @@ recording::context::new_call (recording::location *loc, function *func, int numargs , recording::rvalue **args) { + int min_num_params = func->get_params ().length (); + bool is_variadic = func->is_variadic (); + if (numargs < min_num_params) + { + add_error (("gcc_jit_context_new_call: " + "not enough arguments to function \"%s\"" + " (got %i args, expected %i)"), + func->get_name ()->c_str (), + numargs, min_num_params); + return NULL; + } + if (numargs > min_num_params && !is_variadic) + { + add_error (("gcc_jit_context_new_call: " + "too many arguments to function \"%s\"" + " (got %i args, expected %i)"), + func->get_name ()->c_str (), + numargs, min_num_params); + return NULL; + } recording::rvalue *result = new call (this, loc, func, numargs, args); record (result); return result; diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h index 15f5918..94c149b 100644 --- a/gcc/jit/internal-api.h +++ b/gcc/jit/internal-api.h @@ -608,6 +608,10 @@ public: new_loop (location *loc, rvalue *boolval); + string * get_name () const { return m_name; } + vec<param *> get_params () const { return m_params; } + bool is_variadic () const { return m_is_variadic; } + private: location *m_loc; enum gcc_jit_function_kind m_kind; diff --git a/gcc/testsuite/jit.dg/test-error-call-with-not-enough-args.c b/gcc/testsuite/jit.dg/test-error-call-with-not-enough-args.c new file mode 100644 index 0000000..4cfa09e --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-call-with-not-enough-args.c @@ -0,0 +1,86 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +#ifdef __cplusplus +extern "C" { +#endif + + extern void + called_function (void); + +#ifdef __cplusplus +} +#endif + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + extern void called_function (int p); + + void + test_caller () + { + called_function (); // missing arg + } + + and verify that the API complains about the missing argument. + */ + 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); + + /* Declare the imported function. */ + gcc_jit_param *param_p = + gcc_jit_context_new_param (ctxt, NULL, int_type, "p"); + gcc_jit_function *called_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_IMPORTED, + void_type, + "called_function", + 1, ¶m_p, + 0); + + /* Build the test_fn. */ + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_caller", + 0, NULL, + 0); + /* called_function (); */ + gcc_jit_function_add_eval ( + test_fn, NULL, + gcc_jit_context_new_call (ctxt, + NULL, + called_fn, + 0, NULL)); + /* the above has the wrong arg count. */ + +} + +extern void +called_function (void) +{ +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + /* Ensure that mismatching arg count leads to the API giving a NULL + result back. */ + 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_call:" + " not enough arguments to function \"called_function\"" + " (got 0 args, expected 1)")); +} + diff --git a/gcc/testsuite/jit.dg/test-error-call-with-too-many-args.c b/gcc/testsuite/jit.dg/test-error-call-with-too-many-args.c new file mode 100644 index 0000000..bbfb99f --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-call-with-too-many-args.c @@ -0,0 +1,88 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +#ifdef __cplusplus +extern "C" { +#endif + + extern void + called_function (void); + +#ifdef __cplusplus +} +#endif + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + extern void called_function (); + + void + test_caller (int a) + { + called_function (a); + } + + and verify that the API complains about the mismatching arg + counts. + */ + 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); + + /* Declare the imported function. */ + gcc_jit_function *called_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_IMPORTED, + void_type, + "called_function", + 0, NULL, + 0); + + /* Build the test_fn. */ + gcc_jit_param *param_a = + gcc_jit_context_new_param (ctxt, NULL, int_type, "a"); + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_caller", + 1, ¶m_a, + 0); + /* called_function (a); */ + gcc_jit_rvalue *arg = gcc_jit_param_as_rvalue (param_a); + gcc_jit_function_add_eval ( + test_fn, NULL, + gcc_jit_context_new_call (ctxt, + NULL, + called_fn, + 1, &arg)); + /* the above has the wrong arg count. */ + +} + +extern void +called_function (void) +{ +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + /* Ensure that mismatching arg count leads to the API giving a NULL + result back. */ + 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_call:" + " too many arguments to function \"called_function\"" + " (got 1 args, expected 0)")); +} + diff --git a/gcc/testsuite/jit.dg/test-error-null-passed-to-api.c b/gcc/testsuite/jit.dg/test-error-null-passed-to-api.c new file mode 100644 index 0000000..ea4390b --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-null-passed-to-api.c @@ -0,0 +1,31 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + /* Trigger an API error by passing bad data. */ + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + NULL, /* error: this must be non-NULL */ + "hello_world", + 0, NULL, + 0); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + /* Ensure that the bad API usage prevents the API giving a bogus + result back. */ + 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_function: NULL return_type"); +} + diff --git a/gcc/testsuite/jit.dg/test-null-passed-to-api.c b/gcc/testsuite/jit.dg/test-null-passed-to-api.c deleted file mode 100644 index ea4390b..0000000 --- a/gcc/testsuite/jit.dg/test-null-passed-to-api.c +++ /dev/null @@ -1,31 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -#include "libgccjit.h" - -#include "harness.h" - -void -create_code (gcc_jit_context *ctxt, void *user_data) -{ - /* Trigger an API error by passing bad data. */ - gcc_jit_context_new_function (ctxt, NULL, - GCC_JIT_FUNCTION_EXPORTED, - NULL, /* error: this must be non-NULL */ - "hello_world", - 0, NULL, - 0); -} - -void -verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) -{ - /* Ensure that the bad API usage prevents the API giving a bogus - result back. */ - 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_function: NULL return_type"); -} - -- 1.7.11.7