aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-04-28 18:21:22 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2025-04-28 18:21:22 -0400
commit6f9764571d2dd1b03e41be18b0bcd4fa445b958f (patch)
tree4b9fb8951091f9cb9eeadeea29a70c644d3f82d5 /gcc
parent4e1f545df9da1d2e6f9189c6d289a4875f1e24e3 (diff)
downloadgcc-6f9764571d2dd1b03e41be18b0bcd4fa445b958f.zip
gcc-6f9764571d2dd1b03e41be18b0bcd4fa445b958f.tar.gz
gcc-6f9764571d2dd1b03e41be18b0bcd4fa445b958f.tar.bz2
analyzer: use unique_ptr for state_machine instances
gcc/analyzer/ChangeLog: * engine.cc (class plugin_analyzer_init_impl): Convert "m_checkers" to use std::vector of std::unique_ptr. Convert "m_known_fn_mgr" to a reference. (impl_run_checkers): Convert "checkers" to use std::vector of std::unique_ptr and move it into the extrinsic_state. * program-state.cc (extrinsic_state::dump_to_pp): Update for changes to m_checkers. (extrinsic_state::to_json): Likewise. (extrinsic_state::get_sm_idx_by_name): Likewise. (selftest::test_sm_state_map): Update to use std::unique_ptr for state machines. (selftest::test_program_state_1): Likewise. (selftest::test_program_state_2): Likewise. (selftest::test_program_state_merging): Likewise. (selftest::test_program_state_merging_2): Likewise. * program-state.h (class extrinsic_state): Convert "m_checkers" to use std::vector of std::unique_ptr and to be owned by this object, rather than a reference. Add ctor for use in selftests. * sm-fd.cc (make_fd_state_machine): Update to use std::unique_ptr. * sm-file.cc (make_fileptr_state_machine): Likewise. * sm-malloc.cc (make_malloc_state_machine): Likewise. * sm-pattern-test.cc (make_pattern_test_state_machine): Likewise. * sm-sensitive.cc (make_sensitive_state_machine): Likewise. * sm-signal.cc (make_signal_state_machine): Likewise. * sm-taint.cc (make_taint_state_machine): Likewise. * sm.cc: Define INCLUDE_LIST. (make_checkers): Return the vector directly, rather than pass it in by reference. Update to use std::unique_ptr throughout. Use an intermediate list, and use that to filter with flag_analyzer_checker, fixing memory leak for this case. * sm.h: (make_checkers): Return the vector directly, rather than pass it in by reference, and use std::vector of std::unique_ptr. (make_malloc_state_machine): Convert return type to use std::unique_ptr. (make_fileptr_state_machine): Likewise. (make_taint_state_machine): Likewise. (make_sensitive_state_machine): Likewise. (make_signal_state_machine): Likewise. (make_pattern_test_state_machine): Likewise. (make_va_list_state_machine): Likewise. (make_fd_state_machine): Likewise. * varargs.cc (make_va_list_state_machine): Update to use std::unique_ptr. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/engine.cc28
-rw-r--r--gcc/analyzer/program-state.cc63
-rw-r--r--gcc/analyzer/program-state.h20
-rw-r--r--gcc/analyzer/sm-fd.cc4
-rw-r--r--gcc/analyzer/sm-file.cc4
-rw-r--r--gcc/analyzer/sm-malloc.cc4
-rw-r--r--gcc/analyzer/sm-pattern-test.cc4
-rw-r--r--gcc/analyzer/sm-sensitive.cc4
-rw-r--r--gcc/analyzer/sm-signal.cc4
-rw-r--r--gcc/analyzer/sm-taint.cc4
-rw-r--r--gcc/analyzer/sm.cc44
-rw-r--r--gcc/analyzer/sm.h22
-rw-r--r--gcc/analyzer/varargs.cc4
13 files changed, 108 insertions, 101 deletions
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index f33cc0b..c04bda1 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -6103,8 +6103,8 @@ dump_analyzer_json (const supergraph &sg,
class plugin_analyzer_init_impl : public plugin_analyzer_init_iface
{
public:
- plugin_analyzer_init_impl (auto_delete_vec <state_machine> *checkers,
- known_function_manager *known_fn_mgr,
+ plugin_analyzer_init_impl (std::vector<std::unique_ptr<state_machine>> &checkers,
+ known_function_manager &known_fn_mgr,
logger *logger)
: m_checkers (checkers),
m_known_fn_mgr (known_fn_mgr),
@@ -6114,14 +6114,14 @@ public:
void register_state_machine (std::unique_ptr<state_machine> sm) final override
{
LOG_SCOPE (m_logger);
- m_checkers->safe_push (sm.release ());
+ m_checkers.push_back (std::move (sm));
}
void register_known_function (const char *name,
std::unique_ptr<known_function> kf) final override
{
LOG_SCOPE (m_logger);
- m_known_fn_mgr->add (name, std::move (kf));
+ m_known_fn_mgr.add (name, std::move (kf));
}
logger *get_logger () const final override
@@ -6130,8 +6130,8 @@ public:
}
private:
- auto_delete_vec <state_machine> *m_checkers;
- known_function_manager *m_known_fn_mgr;
+ std::vector<std::unique_ptr<state_machine>> &m_checkers;
+ known_function_manager &m_known_fn_mgr;
logger *m_logger;
};
@@ -6185,27 +6185,25 @@ impl_run_checkers (logger *logger)
free (filename);
}
- auto_delete_vec <state_machine> checkers;
- make_checkers (checkers, logger);
+ auto checkers = make_checkers (logger);
register_known_functions (*eng.get_known_function_manager (),
*eng.get_model_manager ());
- plugin_analyzer_init_impl data (&checkers,
- eng.get_known_function_manager (),
+ plugin_analyzer_init_impl data (checkers,
+ *eng.get_known_function_manager (),
logger);
invoke_plugin_callbacks (PLUGIN_ANALYZER_INIT, &data);
if (logger)
{
- int i;
- state_machine *sm;
- FOR_EACH_VEC_ELT (checkers, i, sm)
- logger->log ("checkers[%i]: %s", i, sm->get_name ());
+ int i = 0;
+ for (auto &sm : checkers)
+ logger->log ("checkers[%i]: %s", ++i, sm->get_name ());
}
/* Extrinsic state shared by nodes in the graph. */
- const extrinsic_state ext_state (checkers, &eng, logger);
+ const extrinsic_state ext_state (std::move (checkers), &eng, logger);
const analysis_plan plan (sg, logger);
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 32b5007..4d3fec0 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -61,11 +61,10 @@ void
extrinsic_state::dump_to_pp (pretty_printer *pp) const
{
pp_printf (pp, "extrinsic_state: %i checker(s)\n", get_num_checkers ());
- unsigned i;
- state_machine *checker;
- FOR_EACH_VEC_ELT (m_checkers, i, checker)
+ unsigned i = 0;
+ for (auto &checker : m_checkers)
{
- pp_printf (pp, "m_checkers[%i]: %qs\n", i, checker->get_name ());
+ pp_printf (pp, "m_checkers[%i]: %qs\n", ++i, checker->get_name ());
checker->dump_to_pp (pp);
}
}
@@ -97,9 +96,7 @@ extrinsic_state::to_json () const
{
auto checkers_arr = ::make_unique<json::array> ();
- unsigned i;
- state_machine *sm;
- FOR_EACH_VEC_ELT (m_checkers, i, sm)
+ for (auto &sm : m_checkers)
checkers_arr->append (sm->to_json ());
ext_state_obj->set ("checkers", std::move (checkers_arr));
}
@@ -125,10 +122,8 @@ extrinsic_state::get_model_manager () const
bool
extrinsic_state::get_sm_idx_by_name (const char *name, unsigned *out) const
{
- unsigned i;
- state_machine *sm;
- FOR_EACH_VEC_ELT (m_checkers, i, sm)
- if (0 == strcmp (name, sm->get_name ()))
+ for (size_t i = 0; i < m_checkers.size (); ++i)
+ if (0 == strcmp (name, m_checkers[i]->get_name ()))
{
/* Found NAME. */
*out = i;
@@ -1783,12 +1778,13 @@ test_sm_state_map ()
tree y = build_global_decl ("y", integer_type_node);
tree z = build_global_decl ("z", integer_type_node);
- state_machine *sm = make_malloc_state_machine (NULL);
- auto_delete_vec <state_machine> checkers;
- checkers.safe_push (sm);
- engine eng;
- extrinsic_state ext_state (checkers, &eng);
+ std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL);
state_machine::state_t start = sm->get_start_state ();
+ std::vector<std::unique_ptr<state_machine>> checkers;
+ const state_machine &borrowed_sm = *sm.get ();
+ checkers.push_back (std::move (sm));
+ engine eng;
+ extrinsic_state ext_state (std::move (checkers), &eng);
/* Test setting states on svalue_id instances directly. */
{
@@ -1800,7 +1796,7 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map (*sm);
+ sm_state_map map (borrowed_sm);
ASSERT_TRUE (map.is_empty_p ());
ASSERT_EQ (map.get_state (x_sval, ext_state), start);
@@ -1829,7 +1825,7 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map (*sm);
+ sm_state_map map (borrowed_sm);
ASSERT_TRUE (map.is_empty_p ());
ASSERT_EQ (map.get_state (x_sval, ext_state), start);
ASSERT_EQ (map.get_state (y_sval, ext_state), start);
@@ -1852,9 +1848,9 @@ test_sm_state_map ()
const svalue *y_sval = model.get_rvalue (y, NULL);
const svalue *z_sval = model.get_rvalue (z, NULL);
- sm_state_map map0 (*sm);
- sm_state_map map1 (*sm);
- sm_state_map map2 (*sm);
+ sm_state_map map0 (borrowed_sm);
+ sm_state_map map1 (borrowed_sm);
+ sm_state_map map2 (borrowed_sm);
ASSERT_EQ (map0.hash (), map1.hash ());
ASSERT_EQ (map0, map1);
@@ -1875,9 +1871,9 @@ test_sm_state_map ()
const state_machine::state_t TEST_STATE_2 = &test_state_2;
const state_machine::state test_state_3 ("test state 3", 3);
const state_machine::state_t TEST_STATE_3 = &test_state_3;
- sm_state_map map0 (*sm);
- sm_state_map map1 (*sm);
- sm_state_map map2 (*sm);
+ sm_state_map map0 (borrowed_sm);
+ sm_state_map map1 (borrowed_sm);
+ sm_state_map map2 (borrowed_sm);
ASSERT_EQ (map0.hash (), map1.hash ());
ASSERT_EQ (map0, map1);
@@ -1912,14 +1908,12 @@ test_program_state_1 ()
malloc sm-state, pointing to a region on the heap. */
tree p = build_global_decl ("p", ptr_type_node);
- state_machine *sm = make_malloc_state_machine (NULL);
+ std::unique_ptr<state_machine> sm = make_malloc_state_machine (NULL);
const state_machine::state_t UNCHECKED_STATE
= sm->get_state_by_name ("unchecked");
- auto_delete_vec <state_machine> checkers;
- checkers.safe_push (sm);
engine eng;
- extrinsic_state ext_state (checkers, &eng);
+ extrinsic_state ext_state (std::move (sm), &eng);
region_model_manager *mgr = eng.get_model_manager ();
program_state s (ext_state);
region_model *model = s.m_region_model;
@@ -1947,9 +1941,9 @@ test_program_state_2 ()
tree string_cst_ptr = build_string_literal (4, "foo");
- auto_delete_vec <state_machine> checkers;
+ std::vector<std::unique_ptr<state_machine>> checkers;
engine eng;
- extrinsic_state ext_state (checkers, &eng);
+ extrinsic_state ext_state (std::move (checkers), &eng);
program_state s (ext_state);
region_model *model = s.m_region_model;
@@ -1971,9 +1965,8 @@ test_program_state_merging ()
engine eng;
region_model_manager *mgr = eng.get_model_manager ();
program_point point (program_point::origin (*mgr));
- auto_delete_vec <state_machine> checkers;
- checkers.safe_push (make_malloc_state_machine (NULL));
- extrinsic_state ext_state (checkers, &eng);
+ extrinsic_state ext_state (make_malloc_state_machine (NULL),
+ &eng);
program_state s0 (ext_state);
uncertainty_t uncertainty;
@@ -2039,9 +2032,7 @@ test_program_state_merging_2 ()
engine eng;
region_model_manager *mgr = eng.get_model_manager ();
program_point point (program_point::origin (*mgr));
- auto_delete_vec <state_machine> checkers;
- checkers.safe_push (make_signal_state_machine (NULL));
- extrinsic_state ext_state (checkers, &eng);
+ extrinsic_state ext_state (make_signal_state_machine (NULL), &eng);
const state_machine::state test_state_0 ("test state 0", 0);
const state_machine::state test_state_1 ("test state 1", 1);
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 48563a9..269ffde 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -30,13 +30,25 @@ namespace ana {
class extrinsic_state
{
public:
- extrinsic_state (auto_delete_vec <state_machine> &checkers,
+ extrinsic_state (std::vector<std::unique_ptr<state_machine>> &&checkers,
engine *eng,
logger *logger = NULL)
- : m_checkers (checkers), m_logger (logger), m_engine (eng)
+ : m_checkers (std::move (checkers)),
+ m_logger (logger),
+ m_engine (eng)
{
}
+ // For use in selftests that use just one state machine
+ extrinsic_state (std::unique_ptr<state_machine> sm,
+ engine *eng,
+ logger *logger = NULL)
+ : m_logger (logger),
+ m_engine (eng)
+ {
+ m_checkers.push_back (std::move (sm));
+ }
+
const state_machine &get_sm (int idx) const
{
return *m_checkers[idx];
@@ -47,7 +59,7 @@ public:
return m_checkers[idx]->get_name ();
}
- unsigned get_num_checkers () const { return m_checkers.length (); }
+ unsigned get_num_checkers () const { return m_checkers.size (); }
logger *get_logger () const { return m_logger; }
@@ -64,7 +76,7 @@ public:
private:
/* The state machines. */
- auto_delete_vec <state_machine> &m_checkers;
+ std::vector<std::unique_ptr<state_machine>> m_checkers;
logger *m_logger;
engine *m_engine;
diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 3119b13..dd9ae93 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -2327,10 +2327,10 @@ fd_state_machine::on_leak (tree var) const
}
} // namespace
-state_machine *
+std::unique_ptr<state_machine>
make_fd_state_machine (logger *logger)
{
- return new fd_state_machine (logger);
+ return std::make_unique<fd_state_machine> (logger);
}
static bool
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index 7de7663c..319ac01 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -500,10 +500,10 @@ fileptr_state_machine::on_leak (tree var) const
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_fileptr_state_machine (logger *logger)
{
- return new fileptr_state_machine (logger);
+ return std::make_unique<fileptr_state_machine> (logger);
}
/* Handler for various stdio-related builtins that merely have external
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index aad625e..ad7974e 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -2698,10 +2698,10 @@ malloc_state_machine::transition_ptr_sval_non_null (region_model *model,
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_malloc_state_machine (logger *logger)
{
- return new malloc_state_machine (logger);
+ return std::make_unique<malloc_state_machine> (logger);
}
/* Specialcase hook for handling realloc, for use by
diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
index 151e625..f24e8df 100644
--- a/gcc/analyzer/sm-pattern-test.cc
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -146,10 +146,10 @@ pattern_test_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_pattern_test_state_machine (logger *logger)
{
- return new pattern_test_state_machine (logger);
+ return std::make_unique<pattern_test_state_machine> (logger);
}
} // namespace ana
diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc
index 3ffe30d..385573b 100644
--- a/gcc/analyzer/sm-sensitive.cc
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -242,10 +242,10 @@ sensitive_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_sensitive_state_machine (logger *logger)
{
- return new sensitive_state_machine (logger);
+ return std::make_unique<sensitive_state_machine> (logger);
}
} // namespace ana
diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc
index 1e74151..2521c7c 100644
--- a/gcc/analyzer/sm-signal.cc
+++ b/gcc/analyzer/sm-signal.cc
@@ -369,10 +369,10 @@ signal_state_machine::can_purge_p (state_t s ATTRIBUTE_UNUSED) const
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_signal_state_machine (logger *logger)
{
- return new signal_state_machine (logger);
+ return std::make_unique<signal_state_machine> (logger);
}
#if CHECKING_P
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index efbc483..21ce68e 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1518,10 +1518,10 @@ taint_state_machine::check_for_tainted_divisor (sm_context &sm_ctxt,
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_taint_state_machine (logger *logger)
{
- return new taint_state_machine (logger);
+ return std::make_unique<taint_state_machine> (logger);
}
/* A closed concrete range. */
diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc
index f1590f7..4328e3c 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+#define INCLUDE_LIST
#include "analyzer/common.h"
#include "tree-diagnostic.h"
@@ -169,35 +170,40 @@ sm_context::get_old_region_model () const
}
/* Create instances of the various state machines, each using LOGGER,
- and populate OUT with them. */
+ returning a vector of them. */
-void
-make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
+std::vector<std::unique_ptr<state_machine>>
+make_checkers (logger *logger)
{
- out.safe_push (make_malloc_state_machine (logger));
- out.safe_push (make_fileptr_state_machine (logger));
- out.safe_push (make_fd_state_machine (logger));
- out.safe_push (make_taint_state_machine (logger));
- out.safe_push (make_sensitive_state_machine (logger));
- out.safe_push (make_signal_state_machine (logger));
- out.safe_push (make_va_list_state_machine (logger));
+ /* Start with a list so that we can filter it. */
+ std::list<std::unique_ptr<state_machine>> out;
+ out.push_back (make_malloc_state_machine (logger));
+ out.push_back (make_fileptr_state_machine (logger));
+ out.push_back (make_fd_state_machine (logger));
+ out.push_back (make_taint_state_machine (logger));
+ out.push_back (make_sensitive_state_machine (logger));
+ out.push_back (make_signal_state_machine (logger));
+ out.push_back (make_va_list_state_machine (logger));
/* We only attempt to run the pattern tests if it might have been manually
enabled (for DejaGnu purposes). */
if (flag_analyzer_checker)
- out.safe_push (make_pattern_test_state_machine (logger));
+ out.push_back (make_pattern_test_state_machine (logger));
if (flag_analyzer_checker)
{
- unsigned read_index, write_index;
- state_machine **sm;
-
- /* TODO: this leaks the machines
- Would be nice to log the things that were removed. */
- VEC_ORDERED_REMOVE_IF (out, read_index, write_index, sm,
- 0 != strcmp (flag_analyzer_checker,
- (*sm)->get_name ()));
+ out.remove_if ([] (auto &sm)
+ {
+ return 0 != strcmp (flag_analyzer_checker,
+ sm->get_name ());
+ });
}
+
+ std::vector<std::unique_ptr<state_machine>> out_vec;
+ for (auto &iter: out)
+ out_vec.push_back (std::move (iter));
+
+ return out_vec;
}
} // namespace ana
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index 6cdb161..a932765 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -341,17 +341,17 @@ protected:
/* The various state_machine subclasses are hidden in their respective
implementation files. */
-extern void make_checkers (auto_delete_vec <state_machine> &out,
- logger *logger);
-
-extern state_machine *make_malloc_state_machine (logger *logger);
-extern state_machine *make_fileptr_state_machine (logger *logger);
-extern state_machine *make_taint_state_machine (logger *logger);
-extern state_machine *make_sensitive_state_machine (logger *logger);
-extern state_machine *make_signal_state_machine (logger *logger);
-extern state_machine *make_pattern_test_state_machine (logger *logger);
-extern state_machine *make_va_list_state_machine (logger *logger);
-extern state_machine *make_fd_state_machine (logger *logger);
+extern std::vector<std::unique_ptr<state_machine>>
+make_checkers (logger *logger);
+
+extern std::unique_ptr<state_machine> make_malloc_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_fileptr_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_taint_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_sensitive_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_signal_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_pattern_test_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_va_list_state_machine (logger *);
+extern std::unique_ptr<state_machine> make_fd_state_machine (logger *);
} // namespace ana
diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc
index 7e0854c..55730a3 100644
--- a/gcc/analyzer/varargs.cc
+++ b/gcc/analyzer/varargs.cc
@@ -642,10 +642,10 @@ va_list_state_machine::on_leak (tree var) const
/* Internal interface to this file. */
-state_machine *
+std::unique_ptr<state_machine>
make_va_list_state_machine (logger *logger)
{
- return new va_list_state_machine (logger);
+ return std::make_unique<va_list_state_machine> (logger);
}
/* Handler for "__builtin_va_start". */