static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
- bool, bool, tree *, vec<c_token>,
+ bool, bool, tree * = NULL,
+ vec<c_token> * = NULL,
bool have_attrs = false,
tree attrs = NULL,
struct oacc_routine_data * = NULL,
an @interface or @protocol with prefix attributes). We can
only tell which after parsing the declaration specifiers, if
any, and the first declarator. */
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true);
break;
}
}
-static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok,
- tree *objc_foreach_object_declaration,
- vec<c_token> omp_declare_simd_clauses,
- bool have_attrs, tree attrs,
- struct oacc_routine_data *oacc_routine_data,
- bool *fallthru_attr_p)
+ tree *objc_foreach_object_declaration
+ /* = NULL */,
+ vec<c_token> *omp_declare_simd_clauses
+ /* = NULL */,
+ bool have_attrs /* = false */,
+ tree attrs /* = NULL_TREE */,
+ struct oacc_routine_data *oacc_routine_data
+ /* = NULL */,
+ bool *fallthru_attr_p /* = NULL */)
{
struct c_declspecs *specs;
tree prefix_attrs;
C_DTR_NORMAL, &dummy);
if (declarator == NULL)
{
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
if (oacc_routine_data)
chainon (postfix_attrs, all_prefix_attrs));
if (!d)
d = error_mark_node;
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
}
chainon (postfix_attrs, all_prefix_attrs));
if (!d)
d = error_mark_node;
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
init_loc = c_parser_peek_token (parser)->location;
warn_parm_array_mismatch (lastloc, d, parms);
}
}
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
{
tree parms = NULL_TREE;
if (d && TREE_CODE (d) == FUNCTION_DECL)
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
c_parser_declaration_or_fndef (parser, false, false, false,
- true, false, NULL, vNULL);
+ true, false);
store_parm_decls ();
- if (omp_declare_simd_clauses.exists ())
+ if (omp_declare_simd_clauses)
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
if (oacc_routine_data)
bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
true, true, true, NULL,
- vNULL, have_std_attrs, std_attrs,
+ NULL, have_std_attrs, std_attrs,
NULL, &fallthru_attr_p);
if (last_stmt && !fallthru_attr_p)
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL);
+ true);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
|| c_parser_nth_token_starts_std_attributes (parser, 1))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- &object_expression, vNULL);
+ &object_expression);
parser->objc_could_be_foreach_context = false;
if (c_parser_next_token_is_keyword (parser, RID_IN))
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, &object_expression, vNULL);
+ true, &object_expression);
parser->objc_could_be_foreach_context = false;
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, false, false, true,
- false, true, NULL, vNULL);
+ false, true);
break;
}
}
while (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION);
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL, false, NULL, &data);
+ NULL, NULL, false, NULL, &data);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, vNULL, false, NULL, &data);
+ NULL, NULL, false, NULL, &data);
}
}
vec_safe_push (for_block, c_begin_compound_stmt (true));
this_pre_body = push_stmt_list ();
c_in_omp_for = true;
- c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, vNULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true);
c_in_omp_for = false;
if (this_pre_body)
{
while (c_parser_next_token_is (parser, CPP_KEYWORD)
&& c_parser_peek_token (parser)->keyword == RID_EXTENSION);
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, clauses);
+ NULL, &clauses);
restore_extension_diagnostics (ext);
}
else
c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, clauses);
+ NULL, &clauses);
break;
case pragma_struct:
case pragma_param:
if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, clauses);
+ true, NULL, &clauses);
restore_extension_diagnostics (ext);
break;
}
else if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, clauses);
+ NULL, &clauses);
break;
}
error ("%<#pragma omp declare %s%> must be followed by "
static void
c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
- vec<c_token> clauses)
+ vec<c_token> *pclauses)
{
+ vec<c_token> &clauses = *pclauses;
+
/* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
indicates error has been reported and CPP_PRAGMA that
c_finish_omp_declare_simd has already processed the tokens. */
from BBS. */
static void
-prune_bbs_to_update_dominators (vec<basic_block> bbs,
+prune_bbs_to_update_dominators (vec<basic_block> &bbs,
bool conservative)
{
unsigned i;
a block of BBS in the current dominance tree dominate it. */
void
-iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> bbs,
+iterate_fix_dominators (enum cdi_direction dir, vec<basic_block> &bbs,
bool conservative)
{
unsigned i;
basic_block recompute_dominator (enum cdi_direction, basic_block);
extern void iterate_fix_dominators (enum cdi_direction,
- vec<basic_block> , bool);
+ vec<basic_block> &, bool);
extern void add_to_dominance_info (enum cdi_direction, basic_block);
extern void delete_from_dominance_info (enum cdi_direction, basic_block);
extern basic_block first_dom_son (enum cdi_direction, basic_block);
get reallocated, the member vectors and the underlying auto_vecs would get
out of sync. */
ipa_call_arg_values (ipa_auto_call_arg_values *aavals)
- : m_known_vals (aavals->m_known_vals),
- m_known_contexts (aavals->m_known_contexts),
- m_known_aggs (aavals->m_known_aggs),
- m_known_value_ranges (aavals->m_known_value_ranges)
+ : m_known_vals (aavals->m_known_vals.to_vec_legacy ()),
+ m_known_contexts (aavals->m_known_contexts.to_vec_legacy ()),
+ m_known_aggs (aavals->m_known_aggs.to_vec_legacy ()),
+ m_known_value_ranges (aavals->m_known_value_ranges.to_vec_legacy ())
{}
/* If m_known_vals (vector of known "scalar" values) is sufficiantly long,
/* Dump function for a DATA_DEPENDENCE_RELATION structure. */
DEBUG_FUNCTION void
-dump_data_dependence_relation (FILE *outf,
- struct data_dependence_relation *ddr)
+dump_data_dependence_relation (FILE *outf, const data_dependence_relation *ddr)
{
struct data_reference *dra, *drb;
/* Debug version. */
DEBUG_FUNCTION void
-debug_data_dependence_relation (struct data_dependence_relation *ddr)
+debug_data_dependence_relation (const struct data_dependence_relation *ddr)
{
dump_data_dependence_relation (stderr, ddr);
}
/* Dump into FILE all the dependence relations from DDRS. */
DEBUG_FUNCTION void
-dump_data_dependence_relations (FILE *file,
- vec<ddr_p> ddrs)
+dump_data_dependence_relations (FILE *file, const vec<ddr_p> &ddrs)
{
- for (data_dependence_relation *ddr : ddrs)
+ for (auto ddr : ddrs)
dump_data_dependence_relation (file, ddr);
}
extern void debug_data_references (vec<data_reference_p> );
extern void debug (vec<data_reference_p> &ref);
extern void debug (vec<data_reference_p> *ptr);
-extern void debug_data_dependence_relation (struct data_dependence_relation *);
-extern void dump_data_dependence_relations (FILE *, vec<ddr_p> );
+extern void debug_data_dependence_relation (const data_dependence_relation *);
+extern void dump_data_dependence_relations (FILE *, const vec<ddr_p> &);
extern void debug (vec<ddr_p> &ref);
extern void debug (vec<ddr_p> *ptr);
extern void debug_data_dependence_relations (vec<ddr_p> );
/* Dumps CHAINS to FILE. */
-extern void dump_chains (FILE *, vec<chain_p> );
void
-dump_chains (FILE *file, vec<chain_p> chains)
+dump_chains (FILE *file, const vec<chain_p> &chains)
{
chain_p chain;
unsigned i;
static void
initialize_root_vars_lm (class loop *loop, dref root, bool written,
- vec<tree> *vars, vec<tree> inits,
+ vec<tree> *vars, const vec<tree> &inits,
bitmap tmp_vars)
{
unsigned i;
optimized. */
static unsigned
-determine_unroll_factor (vec<chain_p> chains)
+determine_unroll_factor (const vec<chain_p> &chains)
{
chain_p chain;
unsigned factor = 1, af, nfactor, i;
phi node, record the ssa name that is defined by it. */
static void
-replace_phis_by_defined_names (vec<chain_p> chains)
+replace_phis_by_defined_names (vec<chain_p> &chains)
{
chain_p chain;
dref a;
/* Insert all initializing gimple stmts into LOOP's entry edge. */
static void
-insert_init_seqs (class loop *loop, vec<chain_p> chains)
+insert_init_seqs (class loop *loop, vec<chain_p> &chains)
{
unsigned i;
edge entry = loop_preheader_edge (loop);
fprintf (dump_file, "Unrolling %u times.\n", unroll_factor);
dta.tmp_vars = tmp_vars;
- dta.chains = m_chains;
+ dta.chains = m_chains.to_vec_legacy ();
dta.worker = this;
/* Cfg manipulations performed in tree_transform_and_unroll_loop before
static bool
insert_into_preds_of_block (basic_block block, unsigned int exprnum,
- vec<pre_expr> avail)
+ vec<pre_expr> &avail)
{
pre_expr expr = expression_for_id (exprnum);
pre_expr newphi;
private:
void maybe_register_path (edge taken_edge);
bool find_paths_to_names (basic_block bb, bitmap imports);
- bool resolve_def (tree name, bitmap interesting, vec<tree> worklist);
+ bool resolve_def (tree name, bitmap interesting, vec<tree> &worklist);
bool resolve_phi (gphi *phi, bitmap imports);
edge find_taken_edge (const vec<basic_block> &path);
edge find_taken_edge_cond (const vec<basic_block> &path, gcond *);
// Populate a vector of trees from a bitmap.
static inline void
-populate_worklist (vec<tree> worklist, bitmap bits)
+populate_worklist (vec<tree> &worklist, bitmap bits)
{
bitmap_iterator bi;
unsigned i;
// current path to be constant, register the path, and return TRUE.
bool
-back_threader::resolve_def (tree name, bitmap interesting, vec<tree> worklist)
+back_threader::resolve_def (tree name, bitmap interesting, vec<tree> &worklist)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (name);
static void
vect_check_nonzero_value (loop_vec_info loop_vinfo, tree value)
{
- vec<tree> checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo);
+ const vec<tree> &checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo);
for (unsigned int i = 0; i < checks.length(); ++i)
if (checks[i] == value)
return;
if (do_versioning)
{
- vec<stmt_vec_info> may_misalign_stmts
- = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
+ const vec<stmt_vec_info> &may_misalign_stmts
+ = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
stmt_vec_info stmt_info;
/* It can now be assumed that the data references in the statements
vect_check_lower_bound (loop_vec_info loop_vinfo, tree expr, bool unsigned_p,
poly_uint64 min_value)
{
- vec<vec_lower_bound> lower_bounds = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
+ vec<vec_lower_bound> &lower_bounds
+ = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
for (unsigned int i = 0; i < lower_bounds.length (); ++i)
if (operand_equal_p (lower_bounds[i].expr, expr, 0))
{
typedef pair_hash <tree_operand_hash, tree_operand_hash> tree_pair_hash;
hash_set <tree_pair_hash> compared_objects;
- vec<ddr_p> may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
+ const vec<ddr_p> &may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
vec<dr_with_seg_len_pair_t> &comp_alias_ddrs
= LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
- vec<vec_object_pair> &check_unequal_addrs
+ const vec<vec_object_pair> &check_unequal_addrs
= LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo);
poly_uint64 vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
I4: 6 14 22 30 7 15 23 31. */
void
-vect_permute_store_chain (vec_info *vinfo, vec<tree> dr_chain,
+vect_permute_store_chain (vec_info *vinfo, vec<tree> &dr_chain,
unsigned int length,
stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,
of the negate node. */
static inline bool
-vect_normalize_conj_loc (vec<slp_tree> args, bool *neg_first_p = NULL)
+vect_normalize_conj_loc (vec<slp_tree> &args, bool *neg_first_p = NULL)
{
gcc_assert (args.length () == 2);
bool neg_found = false;
vect_create_vectorized_demotion_stmts (vec_info *vinfo, vec<tree> *vec_oprnds,
int multi_step_cvt,
stmt_vec_info stmt_info,
- vec<tree> vec_dsts,
+ vec<tree> &vec_dsts,
gimple_stmt_iterator *gsi,
slp_tree slp_node, enum tree_code code)
{
extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
extern bool vect_grouped_load_supported (tree, bool, unsigned HOST_WIDE_INT);
extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
-extern void vect_permute_store_chain (vec_info *,
- vec<tree> ,unsigned int, stmt_vec_info,
+extern void vect_permute_store_chain (vec_info *, vec<tree> &,
+ unsigned int, stmt_vec_info,
gimple_stmt_iterator *, vec<tree> *);
extern tree vect_setup_realignment (vec_info *,
stmt_vec_info, gimple_stmt_iterator *,
#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
{
v.safe_push (i);
}
+/* Verify forms of initialization. */
+
+static void
+test_init ()
+{
+ {
+ vec<int> v1{ };
+ ASSERT_EQ (0, v1.length ());
+
+ vec<int> v2 (v1);
+ ASSERT_EQ (0, v2.length ());
+ }
+
+ {
+ vec<int> v1 = vec<int>();
+ ASSERT_EQ (0, v1.length ());
+
+ vec<int> v2 = v1;
+ ASSERT_EQ (0, v2.length ());
+ }
+
+ {
+ vec<int> v1 (vNULL);
+ ASSERT_EQ (0, v1.length ());
+ v1.safe_push (1);
+
+ vec<int> v2 (v1);
+ ASSERT_EQ (1, v1.length ());
+ v2.safe_push (1);
+
+ ASSERT_EQ (2, v1.length ());
+ ASSERT_EQ (2, v2.length ());
+ v1.release ();
+ }
+}
+
/* Verify that vec::quick_push works correctly. */
static void
void
vec_c_tests ()
{
+ test_init ();
test_quick_push ();
test_safe_push ();
test_truncate ();
::new (static_cast<void*>(dst)) T (*src);
}
-/* Type to provide NULL values for vec<T, A, L>. This is used to
- provide nil initializers for vec instances. Since vec must be
- a POD, we cannot have proper ctor/dtor for it. To initialize
- a vec instance, you can assign it the value vNULL. This isn't
- needed for file-scope and function-local static vectors, which
- are zero-initialized by default. */
-struct vnull
-{
- template <typename T, typename A, typename L>
- CONSTEXPR operator vec<T, A, L> () const { return vec<T, A, L>(); }
-};
-extern vnull vNULL;
+/* Type to provide zero-initialized values for vec<T, A, L>. This is
+ used to provide nil initializers for vec instances. Since vec must
+ be a trivially copyable type that can be copied by memcpy and zeroed
+ out by memset, it must have defaulted default and copy ctor and copy
+ assignment. To initialize a vec either use value initialization
+ (e.g., vec() or vec v{ };) or assign it the value vNULL. This isn't
+ needed for file-scope and function-local static vectors, which are
+ zero-initialized by default. */
+struct vnull { };
+constexpr vnull vNULL{ };
/* Embeddable vector. These vectors are suitable to be embedded
As long as we use C++03, we cannot have constructors nor
destructors in classes that are stored in unions. */
+template<typename T, size_t N = 0>
+class auto_vec;
+
template<typename T>
struct vec<T, va_heap, vl_ptr>
{
public:
+ /* Default ctors to ensure triviality. Use value-initialization
+ (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
+ instance. */
+ vec () = default;
+ vec (const vec &) = default;
+ /* Initialization from the generic vNULL. */
+ vec (vnull): m_vec () { }
+ /* Same as default ctor: vec storage must be released manually. */
+ ~vec () = default;
+
+ /* Defaulted same as copy ctor. */
+ vec& operator= (const vec &) = default;
+
+ /* Prevent implicit conversion from auto_vec. Use auto_vec::to_vec()
+ instead. */
+ template <size_t N>
+ vec (auto_vec<T, N> &) = delete;
+
+ template <size_t N>
+ void operator= (auto_vec<T, N> &) = delete;
+
/* Memory allocation and deallocation for the embedded vector.
Needed because we cannot have proper ctors/dtors defined. */
void create (unsigned nelems CXX_MEM_STAT_INFO);
want to ask for internal storage for vectors on the stack because if the
size of the vector is larger than the internal storage that space is wasted.
*/
-template<typename T, size_t N = 0>
+template<typename T, size_t N /* = 0 */>
class auto_vec : public vec<T, va_heap>
{
public:
this->release ();
}
+ /* Explicitly convert to the base class. There is no conversion
+ from a const auto_vec because a copy of the returned vec can
+ be used to modify *THIS.
+ This is a legacy function not to be used in new code. */
+ vec<T, va_heap> to_vec_legacy () {
+ return *static_cast<vec<T, va_heap> *>(this);
+ }
+
private:
vec<T, va_heap, vl_embed> m_auto;
T m_data[MAX (N - 1, 1)];
return *this;
}
+ /* Explicitly convert to the base class. There is no conversion
+ from a const auto_vec because a copy of the returned vec can
+ be used to modify *THIS.
+ This is a legacy function not to be used in new code. */
+ vec<T, va_heap> to_vec_legacy () {
+ return *static_cast<vec<T, va_heap> *>(this);
+ }
+
// You probably don't want to copy a vector, so these are deleted to prevent
// unintentional use. If you really need a copy of the vectors contents you
// can use copy ().
inline vec<T, va_heap, vl_ptr>
vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
{
- vec<T, va_heap, vl_ptr> new_vec = vNULL;
+ vec<T, va_heap, vl_ptr> new_vec{ };
if (length ())
new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
return new_vec;