diff --git a/Makefile b/Makefile index fc8bbeee..d2d6e05f 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ PLUGIN_SOURCE_FILES= \ gcc-python-option.c \ gcc-python-parameter.c \ gcc-python-pass.c \ + gcc-python-pragma.c \ gcc-python-pretty-printer.c \ gcc-python-rtl.c \ gcc-python-tree.c \ diff --git a/gcc-c-api/gcc-callgraph.c b/gcc-c-api/gcc-callgraph.c index aa05a53d..ba2486b7 100644 --- a/gcc-c-api/gcc-callgraph.c +++ b/gcc-c-api/gcc-callgraph.c @@ -23,9 +23,7 @@ #include "ggc.h" #include "tree-ssa-alias.h" #include "basic-block.h" -#if (GCC_VERSION >= 5000) #include "gimple-expr.h" -#endif #include "gimple.h" /*********************************************************** diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c index e8a42aa8..94931c70 100644 --- a/gcc-python-callbacks.c +++ b/gcc-python-callbacks.c @@ -293,6 +293,17 @@ PyGcc_CallbackFor_GGC_END(void *gcc_data, void *user_data) user_data); } +static void +PyGcc_CallbackFor_PRAGMAS(void *gcc_data, void *user_data) +{ + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + PyGcc_FinishInvokingCallback(gstate, + 0, NULL, + user_data); +} PyObject* PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) @@ -376,6 +387,13 @@ PyGcc_RegisterCallback(PyObject *self, PyObject *args, PyObject *kwargs) closure); break; + case PLUGIN_PRAGMAS: + register_callback("python", // FIXME + (enum plugin_event)event, + PyGcc_CallbackFor_PRAGMAS, + closure); + break; + /* PLUGIN_FINISH_DECL was added in gcc 4.7 onwards: */ #ifdef GCC_PYTHON_PLUGIN_CONFIG_has_PLUGIN_FINISH_DECL case PLUGIN_FINISH_DECL: diff --git a/gcc-python-pragma.c b/gcc-python-pragma.c new file mode 100644 index 00000000..15083853 --- /dev/null +++ b/gcc-python-pragma.c @@ -0,0 +1,108 @@ +/* + FIXME: copyright stuff + FIXME: implement support for c_register_pragma_with_data, + c_register_pragma_with_expansion, + c_register_pragma_with_expansion_and_data + */ + +#include +#include "gcc-python.h" +#include "gcc-python-wrappers.h" + +#include "plugin.h" +#include + +static unsigned char * +parse_pragma_params (cpp_reader *pfile) +{ + const cpp_token *token; + unsigned int out = 0; + unsigned int alloced = 120 + out; + unsigned char *result = (unsigned char *) xmalloc (alloced); + + token = cpp_get_token (pfile); + while (token->type != CPP_EOF && token->type != CPP_PRAGMA_EOL) + { + unsigned char *last; + /* Include room for a possible space and the terminating nul. */ + unsigned int len = cpp_token_len (token) + 2; + + if (out + len > alloced) + { + alloced *= 2; + if (out + len > alloced) + alloced = out + len; + result = (unsigned char *) xrealloc (result, alloced); + } + + last = cpp_spell_token (pfile, token, &result[out], 0); + out = last - result; + + token = cpp_get_token (pfile); + if (token->flags & PREV_WHITE) + result[out++] = ' '; + + if (token->type == CPP_PRAGMA_EOL) + _cpp_backup_tokens(pfile, 1); + } + + result[out] = '\0'; + return result; +} + +void handle_python_pragma(struct cpp_reader *cpp_reader, void *data) { + PyObject *callback = NULL; + PyObject *user_args = NULL; + + // unpack the {callback, args} tuple from the pragma registration + PyArg_ParseTuple((PyObject*)data, "OO", &callback, &user_args); + + /* Debug code: */ + if (0) { + printf("handle_python_pragma called\n"); + fprintf(stderr, "cpp_reader: %p\n", cpp_reader); + } + + PyObject * pragma_args = Py_BuildValue("s", parse_pragma_params(cpp_reader)); + PyObject_CallFunctionObjArgs(callback, pragma_args, user_args, NULL); +} + +PyObject* +PyGcc_CRegisterPragma(PyObject *self, PyObject *args) +{ + const char *directive_space = NULL; + const char *directive = NULL; + PyObject *callback = NULL; + PyObject *user_args = NULL; + unsigned char withExpansion = 0; + PyObject *packed_args = NULL; + + // parse the python tuple + if (!PyArg_ParseTuple(args, + "ssOOb:c_register_pragma", + &directive_space, + &directive, + &callback, + &user_args, + &withExpansion)) { + return NULL; + } + + // pack callback and args so that they can be passed as a single argument + // to the pragma handler + packed_args = Py_BuildValue("OO", callback, user_args); + + // register the new callback + if (withExpansion) + { + c_register_pragma_with_expansion_and_data(directive_space, directive, + handle_python_pragma, (void*)packed_args); + } + else + { + c_register_pragma_with_data(directive_space, directive, handle_python_pragma, + (void*)packed_args); + } + + Py_RETURN_NONE; +} diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h index 5cc6437b..1f52d77e 100644 --- a/gcc-python-wrappers.h +++ b/gcc-python-wrappers.h @@ -131,6 +131,10 @@ PyGcc_inform(PyObject *self, PyObject *args, PyObject *kwargs); extern PyObject * PyGccPass_New(struct opt_pass *pass); +/* gcc-python-pragma.c */ +PyObject* +PyGcc_CRegisterPragma(PyObject *self, PyObject *args); + /* gcc-python-location.c: */ PyObject * PyGccLocation_repr(struct PyGccLocation * self); diff --git a/gcc-python.c b/gcc-python.c index 0e75313e..c01d274d 100644 --- a/gcc-python.c +++ b/gcc-python.c @@ -400,6 +400,11 @@ static PyMethodDef GccMethods[] = { (METH_VARARGS | METH_KEYWORDS), "Pre-define a named value in the preprocessor."}, + {"c_register_pragma", + (PyCFunction)PyGcc_CRegisterPragma, + METH_VARARGS, + "Register a callback for whenever a user defined pragma is parsed."}, + /* Diagnostics: */ {"permerror", PyGcc_permerror, METH_VARARGS, NULL}, diff --git a/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt index a305545f..b63a5447 100644 --- a/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt +++ b/tests/cpychecker/absinterp/comparisons/conditionals/stdout.txt @@ -23,4 +23,4 @@ Trace 0: 'taking True path' 'returning' Exception: - (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/conditionals/input.c:29 + (struct PyObject *)0 from tests/cpychecker/absinterp/comparisons/conditionals/input.c:32 diff --git a/tests/plugin/rtl/stdout.txt b/tests/plugin/rtl/stdout.txt index 46f5ad75..77c3c521 100644 --- a/tests/plugin/rtl/stdout.txt +++ b/tests/plugin/rtl/stdout.txt @@ -13,7 +13,7 @@ class Rtl(__builtin__.object) | Data descriptors defined here: | | loc - | Source code location of this expression, as a gcc.Location + | Source code location of this instruction, as a gcc.Location | | operands | Operands of this expression, as a tuple