gcc/ada/ChangeLog: * gcc-interface/trans.c (gigi): Set exact argument of a vector growth function to true. (Attribute_to_gnu): Likewise. gcc/ChangeLog: * alias.c (init_alias_analysis): Set exact argument of a vector growth function to true. * calls.c (internal_arg_pointer_based_exp_scan): Likewise. * cfgbuild.c (find_many_sub_basic_blocks): Likewise. * cfgexpand.c (expand_asm_stmt): Likewise. * cfgrtl.c (rtl_create_basic_block): Likewise. * combine.c (combine_split_insns): Likewise. (combine_instructions): Likewise. * config/aarch64/aarch64-sve-builtins.cc (function_expander::add_output_operand): Likewise. (function_expander::add_input_operand): Likewise. (function_expander::add_integer_operand): Likewise. (function_expander::add_address_operand): Likewise. (function_expander::add_fixed_operand): Likewise. * df-core.c (df_worklist_dataflow_doublequeue): Likewise. * dwarf2cfi.c (update_row_reg_save): Likewise. * early-remat.c (early_remat::init_block_info): Likewise. (early_remat::finalize_candidate_indices): Likewise. * except.c (sjlj_build_landing_pads): Likewise. * final.c (compute_alignments): Likewise. (grow_label_align): Likewise. * function.c (temp_slots_at_level): Likewise. * fwprop.c (build_single_def_use_links): Likewise. (update_uses): Likewise. * gcc.c (insert_wrapper): Likewise. * genautomata.c (create_state_ainsn_table): Likewise. (add_vect): Likewise. (output_dead_lock_vect): Likewise. * genmatch.c (capture_info::capture_info): Likewise. (parser::finish_match_operand): Likewise. * genrecog.c (optimize_subroutine_group): Likewise. (merge_pattern_info::merge_pattern_info): Likewise. (merge_into_decision): Likewise. (print_subroutine_start): Likewise. (main): Likewise. * gimple-loop-versioning.cc (loop_versioning::loop_versioning): Likewise. * gimple.c (gimple_set_bb): Likewise. * graphite-isl-ast-to-gimple.c (translate_isl_ast_node_user): Likewise. * haifa-sched.c (sched_extend_luids): Likewise. (extend_h_i_d): Likewise. * insn-addr.h (insn_addresses_new): Likewise. * ipa-cp.c (gather_context_independent_values): Likewise. (find_more_contexts_for_caller_subset): Likewise. * ipa-devirt.c (final_warning_record::grow_type_warnings): Likewise. (ipa_odr_read_section): Likewise. * ipa-fnsummary.c (evaluate_properties_for_edge): Likewise. (ipa_fn_summary_t::duplicate): Likewise. (analyze_function_body): Likewise. (ipa_merge_fn_summary_after_inlining): Likewise. (read_ipa_call_summary): Likewise. * ipa-icf.c (sem_function::bb_dict_test): Likewise. * ipa-prop.c (ipa_alloc_node_params): Likewise. (parm_bb_aa_status_for_bb): Likewise. (ipa_compute_jump_functions_for_edge): Likewise. (ipa_analyze_node): Likewise. (update_jump_functions_after_inlining): Likewise. (ipa_read_edge_info): Likewise. (read_ipcp_transformation_info): Likewise. (ipcp_transform_function): Likewise. * ipa-reference.c (ipa_reference_write_optimization_summary): Likewise. * ipa-split.c (execute_split_functions): Likewise. * ira.c (find_moveable_pseudos): Likewise. * lower-subreg.c (decompose_multiword_subregs): Likewise. * lto-streamer-in.c (input_eh_regions): Likewise. (input_cfg): Likewise. (input_struct_function_base): Likewise. (input_function): Likewise. * modulo-sched.c (set_node_sched_params): Likewise. (extend_node_sched_params): Likewise. (schedule_reg_moves): Likewise. * omp-general.c (omp_construct_simd_compare): Likewise. * passes.c (pass_manager::create_pass_tab): Likewise. (enable_disable_pass): Likewise. * predict.c (determine_unlikely_bbs): Likewise. * profile.c (compute_branch_probabilities): Likewise. * read-rtl-function.c (function_reader::parse_block): Likewise. * read-rtl.c (rtx_reader::read_rtx_code): Likewise. * reg-stack.c (stack_regs_mentioned): Likewise. * regrename.c (regrename_init): Likewise. * rtlanal.c (T>::add_single_to_queue): Likewise. * sched-deps.c (init_deps_data_vector): Likewise. * sel-sched-ir.c (sel_extend_global_bb_info): Likewise. (extend_region_bb_info): Likewise. (extend_insn_data): Likewise. * symtab.c (symtab_node::create_reference): Likewise. * tracer.c (tail_duplicate): Likewise. * trans-mem.c (tm_region_init): Likewise. (get_bb_regions_instrumented): Likewise. * tree-cfg.c (init_empty_tree_cfg_for_function): Likewise. (build_gimple_cfg): Likewise. (create_bb): Likewise. (move_block_to_fn): Likewise. * tree-complex.c (tree_lower_complex): Likewise. * tree-if-conv.c (predicate_rhs_code): Likewise. * tree-inline.c (copy_bb): Likewise. * tree-into-ssa.c (get_ssa_name_ann): Likewise. (mark_phi_for_rewrite): Likewise. * tree-object-size.c (compute_builtin_object_size): Likewise. (init_object_sizes): Likewise. * tree-predcom.c (initialize_root_vars_store_elim_1): Likewise. (initialize_root_vars_store_elim_2): Likewise. (prepare_initializers_chain_store_elim): Likewise. * tree-ssa-address.c (addr_for_mem_ref): Likewise. (multiplier_allowed_in_address_p): Likewise. * tree-ssa-coalesce.c (ssa_conflicts_new): Likewise. * tree-ssa-forwprop.c (simplify_vector_constructor): Likewise. * tree-ssa-loop-ivopts.c (addr_offset_valid_p): Likewise. (get_address_cost_ainc): Likewise. * tree-ssa-loop-niter.c (discover_iteration_bound_by_body_walk): Likewise. * tree-ssa-pre.c (add_to_value): Likewise. (phi_translate_1): Likewise. (do_pre_regular_insertion): Likewise. (do_pre_partial_partial_insertion): Likewise. (init_pre): Likewise. * tree-ssa-propagate.c (ssa_prop_init): Likewise. (update_call_from_tree): Likewise. * tree-ssa-reassoc.c (optimize_range_tests_cmp_bitwise): Likewise. * tree-ssa-sccvn.c (vn_reference_lookup_3): Likewise. (vn_reference_lookup_pieces): Likewise. (eliminate_dom_walker::eliminate_push_avail): Likewise. * tree-ssa-strlen.c (set_strinfo): Likewise. (get_stridx_plus_constant): Likewise. (zero_length_string): Likewise. (find_equal_ptrs): Likewise. (printf_strlen_execute): Likewise. * tree-ssa-threadedge.c (set_ssa_name_value): Likewise. * tree-ssanames.c (make_ssa_name_fn): Likewise. * tree-streamer-in.c (streamer_read_tree_bitfields): Likewise. * tree-vect-loop.c (vect_record_loop_mask): Likewise. (vect_get_loop_mask): Likewise. (vect_record_loop_len): Likewise. (vect_get_loop_len): Likewise. * tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Likewise. * tree-vect-slp.c (vect_slp_convert_to_external): Likewise. (vect_bb_slp_scalar_cost): Likewise. (vect_bb_vectorization_profitable_p): Likewise. (vectorizable_slp_permutation): Likewise. * tree-vect-stmts.c (vectorizable_call): Likewise. (vectorizable_simd_clone_call): Likewise. (scan_store_can_perm_p): Likewise. (vectorizable_store): Likewise. * expr.c: Likewise. * vec.c (test_safe_grow_cleared): Likewise. * vec.h (vec_safe_grow): Likewise. (vec_safe_grow_cleared): Likewise. (vl_ptr>::safe_grow): Likewise. (vl_ptr>::safe_grow_cleared): Likewise. * config/c6x/c6x.c (insn_set_clock): Likewise. gcc/c/ChangeLog: * gimple-parser.c (c_parser_gimple_compound_statement): Set exact argument of a vector growth function to true. gcc/cp/ChangeLog: * class.c (build_vtbl_initializer): Set exact argument of a vector growth function to true. * constraint.cc (get_mapped_args): Likewise. * decl.c (cp_maybe_mangle_decomp): Likewise. (cp_finish_decomp): Likewise. * parser.c (cp_parser_omp_for_loop): Likewise. * pt.c (canonical_type_parameter): Likewise. * rtti.c (get_pseudo_ti_init): Likewise. gcc/fortran/ChangeLog: * trans-openmp.c (gfc_trans_omp_do): Set exact argument of a vector growth function to true. gcc/lto/ChangeLog: * lto-common.c (lto_file_finalize): Set exact argument of a vector growth function to true.
569 lines
14 KiB
C
569 lines
14 KiB
C
/* Vector API for GNU compiler.
|
|
Copyright (C) 2004-2020 Free Software Foundation, Inc.
|
|
Contributed by Nathan Sidwell <nathan@codesourcery.com>
|
|
Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
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/>. */
|
|
|
|
/* This file is compiled twice: once for the generator programs
|
|
once for the compiler. */
|
|
#ifdef GENERATOR_FILE
|
|
#include "bconfig.h"
|
|
#else
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "hash-table.h"
|
|
#include "selftest.h"
|
|
#ifdef GENERATOR_FILE
|
|
#include "errors.h"
|
|
#else
|
|
#include "input.h"
|
|
#include "diagnostic-core.h"
|
|
#endif
|
|
|
|
/* vNULL is an empty type with a template cast operation that returns
|
|
a zero-initialized vec<T, A, L> instance. Use this when you want
|
|
to assign nil values to new vec instances or pass a nil vector as
|
|
a function call argument.
|
|
|
|
We use this technique because vec<T, A, L> must be PODs (they are
|
|
stored in unions and passed in vararg functions), this means that
|
|
they cannot have ctors/dtors. */
|
|
vnull vNULL;
|
|
|
|
/* Vector memory usage. */
|
|
class vec_usage: public mem_usage
|
|
{
|
|
public:
|
|
/* Default constructor. */
|
|
vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {}
|
|
|
|
/* Constructor. */
|
|
vec_usage (size_t allocated, size_t times, size_t peak,
|
|
size_t items, size_t items_peak, size_t element_size)
|
|
: mem_usage (allocated, times, peak),
|
|
m_items (items), m_items_peak (items_peak),
|
|
m_element_size (element_size) {}
|
|
|
|
/* Sum the usage with SECOND usage. */
|
|
vec_usage
|
|
operator+ (const vec_usage &second)
|
|
{
|
|
return vec_usage (m_allocated + second.m_allocated,
|
|
m_times + second.m_times,
|
|
m_peak + second.m_peak,
|
|
m_items + second.m_items,
|
|
m_items_peak + second.m_items_peak, 0);
|
|
}
|
|
|
|
/* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
|
|
inline void
|
|
dump (mem_location *loc, mem_usage &total) const
|
|
{
|
|
char s[4096];
|
|
sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
|
|
loc->m_line, loc->m_function);
|
|
|
|
s[48] = '\0';
|
|
|
|
fprintf (stderr,
|
|
"%-48s %10" PRIu64 PRsa (10) ":%4.1f%%" PRsa (9) "%10" PRIu64
|
|
":%4.1f%%" PRsa (10) PRsa (10) "\n",
|
|
s,
|
|
(uint64_t)m_element_size,
|
|
SIZE_AMOUNT (m_allocated),
|
|
m_allocated * 100.0 / total.m_allocated,
|
|
SIZE_AMOUNT (m_peak), (uint64_t)m_times,
|
|
m_times * 100.0 / total.m_times,
|
|
SIZE_AMOUNT (m_items), SIZE_AMOUNT (m_items_peak));
|
|
}
|
|
|
|
/* Dump footer. */
|
|
inline void
|
|
dump_footer ()
|
|
{
|
|
fprintf (stderr, "%s" PRsa (64) PRsa (25) PRsa (16) "\n",
|
|
"Total", SIZE_AMOUNT (m_allocated),
|
|
SIZE_AMOUNT (m_times), SIZE_AMOUNT (m_items));
|
|
}
|
|
|
|
/* Dump header with NAME. */
|
|
static inline void
|
|
dump_header (const char *name)
|
|
{
|
|
fprintf (stderr, "%-48s %10s%11s%16s%10s%17s%11s\n", name, "sizeof(T)",
|
|
"Leak", "Peak", "Times", "Leak items", "Peak items");
|
|
}
|
|
|
|
/* Current number of items allocated. */
|
|
size_t m_items;
|
|
/* Peak value of number of allocated items. */
|
|
size_t m_items_peak;
|
|
/* Size of element of the vector. */
|
|
size_t m_element_size;
|
|
};
|
|
|
|
/* Vector memory description. */
|
|
static mem_alloc_description <vec_usage> vec_mem_desc;
|
|
|
|
/* Account the overhead. */
|
|
|
|
void
|
|
vec_prefix::register_overhead (void *ptr, size_t elements,
|
|
size_t element_size MEM_STAT_DECL)
|
|
{
|
|
vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
|
|
FINAL_PASS_MEM_STAT);
|
|
vec_usage *usage
|
|
= vec_mem_desc.register_instance_overhead (elements * element_size, ptr);
|
|
usage->m_element_size = element_size;
|
|
usage->m_items += elements;
|
|
if (usage->m_items_peak < usage->m_items)
|
|
usage->m_items_peak = usage->m_items;
|
|
}
|
|
|
|
/* Notice that the memory allocated for the vector has been freed. */
|
|
|
|
void
|
|
vec_prefix::release_overhead (void *ptr, size_t size, size_t elements,
|
|
bool in_dtor MEM_STAT_DECL)
|
|
{
|
|
if (!vec_mem_desc.contains_descriptor_for_instance (ptr))
|
|
vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN,
|
|
false FINAL_PASS_MEM_STAT);
|
|
vec_usage *usage = vec_mem_desc.release_instance_overhead (ptr, size,
|
|
in_dtor);
|
|
usage->m_items -= elements;
|
|
}
|
|
|
|
/* Calculate the number of slots to reserve a vector, making sure that
|
|
it is of at least DESIRED size by growing ALLOC exponentially. */
|
|
|
|
unsigned
|
|
vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
|
|
{
|
|
/* We must have run out of room. */
|
|
gcc_assert (alloc < desired);
|
|
|
|
/* Exponential growth. */
|
|
if (!alloc)
|
|
alloc = 4;
|
|
else if (alloc < 16)
|
|
/* Double when small. */
|
|
alloc = alloc * 2;
|
|
else
|
|
/* Grow slower when large. */
|
|
alloc = (alloc * 3 / 2);
|
|
|
|
/* If this is still too small, set it to the right size. */
|
|
if (alloc < desired)
|
|
alloc = desired;
|
|
return alloc;
|
|
}
|
|
|
|
/* Dump per-site memory statistics. */
|
|
|
|
void
|
|
dump_vec_loc_statistics (void)
|
|
{
|
|
vec_mem_desc.dump (VEC_ORIGIN);
|
|
}
|
|
|
|
#if CHECKING_P
|
|
/* Report qsort comparator CMP consistency check failure with P1, P2, P3 as
|
|
witness elements. */
|
|
ATTRIBUTE_NORETURN ATTRIBUTE_COLD
|
|
static void
|
|
qsort_chk_error (const void *p1, const void *p2, const void *p3,
|
|
sort_r_cmp_fn *cmp, void *data)
|
|
{
|
|
if (!p3)
|
|
{
|
|
int r1 = cmp (p1, p2, data), r2 = cmp (p2, p1, data);
|
|
error ("qsort comparator not anti-symmetric: %d, %d", r1, r2);
|
|
}
|
|
else if (p1 == p2)
|
|
{
|
|
int r = cmp (p1, p3, data);
|
|
error ("qsort comparator non-negative on sorted output: %d", r);
|
|
}
|
|
else
|
|
{
|
|
int r1 = cmp (p1, p2, data);
|
|
int r2 = cmp (p2, p3, data);
|
|
int r3 = cmp (p1, p3, data);
|
|
error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3);
|
|
}
|
|
internal_error ("qsort checking failed");
|
|
}
|
|
|
|
/* Verify anti-symmetry and transitivity for comparator CMP on sorted array
|
|
of N SIZE-sized elements pointed to by BASE. */
|
|
void
|
|
qsort_chk (void *base, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data)
|
|
{
|
|
#if 0
|
|
#define LIM(n) (n)
|
|
#else
|
|
/* Limit overall time complexity to O(n log n). */
|
|
#define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n))
|
|
#endif
|
|
#define ELT(i) ((const char *) base + (i) * size)
|
|
#define CMP(i, j) cmp (ELT (i), ELT (j), data)
|
|
#define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp, data)
|
|
#define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp, data)
|
|
size_t i1, i2, i, j;
|
|
/* This outer loop iterates over maximum spans [i1, i2) such that
|
|
elements within each span compare equal to each other. */
|
|
for (i1 = 0; i1 < n; i1 = i2)
|
|
{
|
|
/* Position i2 one past last element that compares equal to i1'th. */
|
|
for (i2 = i1 + 1; i2 < n; i2++)
|
|
if (CMP (i1, i2))
|
|
break;
|
|
else if (CMP (i2, i1))
|
|
return ERR2 (i1, i2);
|
|
size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2);
|
|
/* Verify that other pairs within current span compare equal. */
|
|
for (i = i1 + 1; i + 1 < i2; i++)
|
|
for (j = i + 1; j < i1 + lim1; j++)
|
|
if (CMP (i, j))
|
|
return ERR3 (i, i1, j);
|
|
else if (CMP (j, i))
|
|
return ERR2 (i, j);
|
|
/* Verify that elements within this span compare less than
|
|
elements beyond the span. */
|
|
for (i = i1; i < i2; i++)
|
|
for (j = i2; j < i2 + lim2; j++)
|
|
if (CMP (i, j) >= 0)
|
|
return ERR3 (i, i1, j);
|
|
else if (CMP (j, i) <= 0)
|
|
return ERR2 (i, j);
|
|
}
|
|
#undef ERR3
|
|
#undef ERR2
|
|
#undef CMP
|
|
#undef ELT
|
|
#undef LIM
|
|
}
|
|
#endif /* #if CHECKING_P */
|
|
|
|
#ifndef GENERATOR_FILE
|
|
#if CHECKING_P
|
|
|
|
namespace selftest {
|
|
|
|
/* Selftests. */
|
|
|
|
/* Call V.safe_push for all ints from START up to, but not including LIMIT.
|
|
Helper function for selftests. */
|
|
|
|
static void
|
|
safe_push_range (vec <int>&v, int start, int limit)
|
|
{
|
|
for (int i = start; i < limit; i++)
|
|
v.safe_push (i);
|
|
}
|
|
|
|
/* Verify that vec::quick_push works correctly. */
|
|
|
|
static void
|
|
test_quick_push ()
|
|
{
|
|
auto_vec <int> v;
|
|
ASSERT_EQ (0, v.length ());
|
|
v.reserve (3);
|
|
ASSERT_EQ (0, v.length ());
|
|
ASSERT_TRUE (v.space (3));
|
|
v.quick_push (5);
|
|
v.quick_push (6);
|
|
v.quick_push (7);
|
|
ASSERT_EQ (3, v.length ());
|
|
ASSERT_EQ (5, v[0]);
|
|
ASSERT_EQ (6, v[1]);
|
|
ASSERT_EQ (7, v[2]);
|
|
}
|
|
|
|
/* Verify that vec::safe_push works correctly. */
|
|
|
|
static void
|
|
test_safe_push ()
|
|
{
|
|
auto_vec <int> v;
|
|
ASSERT_EQ (0, v.length ());
|
|
v.safe_push (5);
|
|
v.safe_push (6);
|
|
v.safe_push (7);
|
|
ASSERT_EQ (3, v.length ());
|
|
ASSERT_EQ (5, v[0]);
|
|
ASSERT_EQ (6, v[1]);
|
|
ASSERT_EQ (7, v[2]);
|
|
}
|
|
|
|
/* Verify that vec::truncate works correctly. */
|
|
|
|
static void
|
|
test_truncate ()
|
|
{
|
|
auto_vec <int> v;
|
|
ASSERT_EQ (0, v.length ());
|
|
safe_push_range (v, 0, 10);
|
|
ASSERT_EQ (10, v.length ());
|
|
|
|
v.truncate (5);
|
|
ASSERT_EQ (5, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::safe_grow_cleared works correctly. */
|
|
|
|
static void
|
|
test_safe_grow_cleared ()
|
|
{
|
|
auto_vec <int> v;
|
|
ASSERT_EQ (0, v.length ());
|
|
v.safe_grow_cleared (50, true);
|
|
ASSERT_EQ (50, v.length ());
|
|
ASSERT_EQ (0, v[0]);
|
|
ASSERT_EQ (0, v[49]);
|
|
}
|
|
|
|
/* Verify that vec::pop works correctly. */
|
|
|
|
static void
|
|
test_pop ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 5, 20);
|
|
ASSERT_EQ (15, v.length ());
|
|
|
|
int last = v.pop ();
|
|
ASSERT_EQ (19, last);
|
|
ASSERT_EQ (14, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::safe_insert works correctly. */
|
|
|
|
static void
|
|
test_safe_insert ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
v.safe_insert (5, 42);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (42, v[5]);
|
|
ASSERT_EQ (5, v[6]);
|
|
ASSERT_EQ (11, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::ordered_remove works correctly. */
|
|
|
|
static void
|
|
test_ordered_remove ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
v.ordered_remove (5);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (6, v[5]);
|
|
ASSERT_EQ (9, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::ordered_remove_if works correctly. */
|
|
|
|
static void
|
|
test_ordered_remove_if (void)
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
unsigned ix, ix2;
|
|
int *elem_ptr;
|
|
VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr,
|
|
*elem_ptr == 5 || *elem_ptr == 7);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (6, v[5]);
|
|
ASSERT_EQ (8, v[6]);
|
|
ASSERT_EQ (8, v.length ());
|
|
|
|
v.truncate (0);
|
|
safe_push_range (v, 0, 10);
|
|
VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 6,
|
|
*elem_ptr == 5 || *elem_ptr == 7);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (6, v[5]);
|
|
ASSERT_EQ (7, v[6]);
|
|
ASSERT_EQ (9, v.length ());
|
|
|
|
v.truncate (0);
|
|
safe_push_range (v, 0, 10);
|
|
VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 5,
|
|
*elem_ptr == 5 || *elem_ptr == 7);
|
|
VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 8, 10,
|
|
*elem_ptr == 5 || *elem_ptr == 7);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (5, v[5]);
|
|
ASSERT_EQ (6, v[6]);
|
|
ASSERT_EQ (10, v.length ());
|
|
|
|
v.truncate (0);
|
|
safe_push_range (v, 0, 10);
|
|
VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr, *elem_ptr == 5);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (6, v[5]);
|
|
ASSERT_EQ (7, v[6]);
|
|
ASSERT_EQ (9, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::unordered_remove works correctly. */
|
|
|
|
static void
|
|
test_unordered_remove ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
v.unordered_remove (5);
|
|
ASSERT_EQ (9, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::block_remove works correctly. */
|
|
|
|
static void
|
|
test_block_remove ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
v.block_remove (5, 3);
|
|
ASSERT_EQ (3, v[3]);
|
|
ASSERT_EQ (4, v[4]);
|
|
ASSERT_EQ (8, v[5]);
|
|
ASSERT_EQ (9, v[6]);
|
|
ASSERT_EQ (7, v.length ());
|
|
}
|
|
|
|
/* Comparator for use by test_qsort. */
|
|
|
|
static int
|
|
reverse_cmp (const void *p_i, const void *p_j)
|
|
{
|
|
return *(const int *)p_j - *(const int *)p_i;
|
|
}
|
|
|
|
/* Verify that vec::qsort works correctly. */
|
|
|
|
static void
|
|
test_qsort ()
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 10);
|
|
v.qsort (reverse_cmp);
|
|
ASSERT_EQ (9, v[0]);
|
|
ASSERT_EQ (8, v[1]);
|
|
ASSERT_EQ (1, v[8]);
|
|
ASSERT_EQ (0, v[9]);
|
|
ASSERT_EQ (10, v.length ());
|
|
}
|
|
|
|
/* Verify that vec::reverse works correctly. */
|
|
|
|
static void
|
|
test_reverse ()
|
|
{
|
|
/* Reversing an empty vec ought to be a no-op. */
|
|
{
|
|
auto_vec <int> v;
|
|
ASSERT_EQ (0, v.length ());
|
|
v.reverse ();
|
|
ASSERT_EQ (0, v.length ());
|
|
}
|
|
|
|
/* Verify reversing a vec with even length. */
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 4);
|
|
v.reverse ();
|
|
ASSERT_EQ (3, v[0]);
|
|
ASSERT_EQ (2, v[1]);
|
|
ASSERT_EQ (1, v[2]);
|
|
ASSERT_EQ (0, v[3]);
|
|
ASSERT_EQ (4, v.length ());
|
|
}
|
|
|
|
/* Verify reversing a vec with odd length. */
|
|
{
|
|
auto_vec <int> v;
|
|
safe_push_range (v, 0, 3);
|
|
v.reverse ();
|
|
ASSERT_EQ (2, v[0]);
|
|
ASSERT_EQ (1, v[1]);
|
|
ASSERT_EQ (0, v[2]);
|
|
ASSERT_EQ (3, v.length ());
|
|
}
|
|
}
|
|
|
|
/* A test class that increments a counter every time its dtor is called. */
|
|
|
|
class count_dtor
|
|
{
|
|
public:
|
|
count_dtor (int *counter) : m_counter (counter) {}
|
|
~count_dtor () { (*m_counter)++; }
|
|
|
|
private:
|
|
int *m_counter;
|
|
};
|
|
|
|
/* Verify that auto_delete_vec deletes the elements within it. */
|
|
|
|
static void
|
|
test_auto_delete_vec ()
|
|
{
|
|
int dtor_count = 0;
|
|
{
|
|
auto_delete_vec <count_dtor> v;
|
|
v.safe_push (new count_dtor (&dtor_count));
|
|
v.safe_push (new count_dtor (&dtor_count));
|
|
}
|
|
ASSERT_EQ (dtor_count, 2);
|
|
}
|
|
|
|
/* Run all of the selftests within this file. */
|
|
|
|
void
|
|
vec_c_tests ()
|
|
{
|
|
test_quick_push ();
|
|
test_safe_push ();
|
|
test_truncate ();
|
|
test_safe_grow_cleared ();
|
|
test_pop ();
|
|
test_safe_insert ();
|
|
test_ordered_remove ();
|
|
test_ordered_remove_if ();
|
|
test_unordered_remove ();
|
|
test_block_remove ();
|
|
test_qsort ();
|
|
test_reverse ();
|
|
test_auto_delete_vec ();
|
|
}
|
|
|
|
} // namespace selftest
|
|
|
|
#endif /* #if CHECKING_P */
|
|
#endif /* #ifndef GENERATOR_FILE */
|