mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 23:51:10 +08:00
This patch adds a new GCC plugin event: PLUGIN_ANALYZER_INIT, called when -fanalyzer is starting, allowing for GCC plugins to register additional state-machine-based checks within -fanalyzer. The idea is that 3rd-party code might want to add domain-specific checks for its own APIs - with the caveat that the analyzer is itself still rather experimental. As an example, the patch adds a proof-of-concept plugin to the testsuite for checking CPython code: verifying that code that relinquishes CPython's global interpreter lock doesn't attempt to do anything with PyObjects in the sections where the lock isn't held. It also adds a warning about nested releases of the lock, which is forbidden. For example: demo.c: In function 'foo': demo.c:11:3: warning: use of PyObject '*(obj)' without the GIL 11 | Py_INCREF (obj); | ^~~~~~~~~ 'test': events 1-3 | | 15 | void test (PyObject *obj) | | ^~~~ | | | | | (1) entry to 'test' | 16 | { | 17 | Py_BEGIN_ALLOW_THREADS | | ~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) releasing the GIL here | 18 | foo (obj); | | ~~~~~~~~~ | | | | | (3) calling 'foo' from 'test' | +--> 'foo': events 4-5 | | 9 | foo (PyObject *obj) | | ^~~ | | | | | (4) entry to 'foo' | 10 | { | 11 | Py_INCREF (obj); | | ~~~~~~~~~ | | | | | (5) PyObject '*(obj)' used here without the GIL | Doing so requires adding some logic for ignoring macro expansions in analyzer diagnostics, since the insides of Py_INCREF and Py_BEGIN_ALLOW_THREADS are not of interest to the user for these cases. gcc/analyzer/ChangeLog: * analyzer-pass.cc (pass_analyzer::execute): Move sorry call to... (sorry_no_analyzer): New. * analyzer.h (class state_machine): New forward decl. (class logger): New forward decl. (class plugin_analyzer_init_iface): New. (sorry_no_analyzer): New decl. * checker-path.cc (checker_path::fixup_locations): New. * checker-path.h (checker_event::set_location): New. (checker_path::fixup_locations): New decl. * diagnostic-manager.cc (diagnostic_manager::emit_saved_diagnostic): Call checker_path::fixup_locations, and call fixup_location on the primary location. * engine.cc: Include "plugin.h". (class plugin_analyzer_init_impl): New. (impl_run_checkers): Invoke PLUGIN_ANALYZER_INIT callbacks. * pending-diagnostic.h (pending_diagnostic::fixup_location): New vfunc. gcc/ChangeLog: * doc/plugins.texi (Plugin callbacks): Add PLUGIN_ANALYZER_INIT. * plugin.c (register_callback): Likewise. (invoke_plugin_callbacks_full): Likewise. * plugin.def (PLUGIN_ANALYZER_INIT): New event. gcc/testsuite/ChangeLog: * gcc.dg/plugin/analyzer_gil_plugin.c: New test. * gcc.dg/plugin/gil-1.c: New test. * gcc.dg/plugin/gil.h: New header. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new plugin and test.