diff options
author | Eric Feng <ef2648@columbia.edu> | 2023-08-30 17:52:24 -0400 |
---|---|---|
committer | Eric Feng <ef2648@columbia.edu> | 2023-08-30 18:04:41 -0400 |
commit | 597b9ec69bca8acb7a3d65641c0a730de8b27ed4 (patch) | |
tree | 9a657e460a8c6de5955922bd23625084faf12da7 /gcc/analyzer/engine.cc | |
parent | 4e1e8752549cde215c4afaad19194003aaa54f7f (diff) | |
download | gcc-597b9ec69bca8acb7a3d65641c0a730de8b27ed4.zip gcc-597b9ec69bca8acb7a3d65641c0a730de8b27ed4.tar.gz gcc-597b9ec69bca8acb7a3d65641c0a730de8b27ed4.tar.bz2 |
analyzer: implement reference count checking for CPython plugin [PR107646]
This patch introduces initial support for reference count checking of
PyObjects in relation to the Python/C API for the CPython plugin.
Additionally, the core analyzer underwent several modifications to
accommodate this feature. These include:
- Introducing support for callbacks at the end of
region_model::pop_frame. This is our current point of validation for
the reference count of PyObjects.
- An added optional custom stmt_finder parameter to
region_model_context::warn. This aids in emitting a diagnostic
concerning the reference count, especially when the stmt_finder is
NULL, which is currently the case during region_model::pop_frame.
The current diagnostic we emit relating to the reference count
appears as follows:
rc3.c:23:10: warning: expected ‘item’ to have reference count: ‘1’ but
ob_refcnt field is: ‘2’
23 | return list;
| ^~~~
‘create_py_object’: events 1-4
|
| 4 | PyObject* item = PyLong_FromLong(3);
| | ^~~~~~~~~~~~~~~~~~
| | |
| | (1) when ‘PyLong_FromLong’ succeeds
| 5 | PyObject* list = PyList_New(1);
| | ~~~~~~~~~~~~~
| | |
| | (2) when ‘PyList_New’ succeeds
|......
| 14 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when ‘PyList_Append’ succeeds, moving buffer
|......
| 23 | return list;
| | ~~~~
| | |
| | (4) here
|
This is a WIP in several ways:
- Currently, functions returning PyObject * are assumed to always
produce a new reference.
- The validation of reference count is only for PyObjects created within
a function body. Verifying reference counts for PyObjects passed as
parameters is not supported in this patch.
gcc/analyzer/ChangeLog:
PR analyzer/107646
* engine.cc (impl_region_model_context::warn): New optional
parameter.
* exploded-graph.h (class impl_region_model_context): Likewise.
* region-model.cc (region_model::pop_frame): New callback
feature for region_model::pop_frame.
* region-model.h (struct append_regions_cb_data): Likewise.
(class region_model): Likewise.
(class region_model_context): New optional parameter.
(class region_model_context_decorator): Likewise.
gcc/testsuite/ChangeLog:
PR analyzer/107646
* gcc.dg/plugin/analyzer_cpython_plugin.c: Implements reference
count checking for PyObjects.
* gcc.dg/plugin/cpython-plugin-test-2.c: Moved to...
* gcc.dg/plugin/cpython-plugin-test-PyList_Append.c: ...here
(and added more tests).
* gcc.dg/plugin/cpython-plugin-test-1.c: Moved to...
* gcc.dg/plugin/cpython-plugin-test-no-Python-h.c: ...here (and
added more tests).
* gcc.dg/plugin/plugin.exp: New tests.
* gcc.dg/plugin/cpython-plugin-test-PyList_New.c: New test.
* gcc.dg/plugin/cpython-plugin-test-PyLong_FromLong.c: New test.
Signed-off-by: Eric Feng <ef2648@columbia.edu>
Diffstat (limited to 'gcc/analyzer/engine.cc')
-rw-r--r-- | gcc/analyzer/engine.cc | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index a1908cd..736a41e 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -115,10 +115,12 @@ impl_region_model_context (program_state *state, } bool -impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d) +impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d, + const stmt_finder *custom_finder) { LOG_FUNC (get_logger ()); - if (m_stmt == NULL && m_stmt_finder == NULL) + auto curr_stmt_finder = custom_finder ? custom_finder : m_stmt_finder; + if (m_stmt == NULL && curr_stmt_finder == NULL) { if (get_logger ()) get_logger ()->log ("rejecting diagnostic: no stmt"); @@ -129,7 +131,7 @@ impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d) bool terminate_path = d->terminate_path_p (); if (m_eg->get_diagnostic_manager ().add_diagnostic (m_enode_for_diag, m_enode_for_diag->get_supernode (), - m_stmt, m_stmt_finder, std::move (d))) + m_stmt, curr_stmt_finder, std::move (d))) { if (m_path_ctxt && terminate_path |