type = TREE_TYPE (decl);
if (type == error_mark_node)
return error_mark_node;
- if (IS_AGGR_TYPE (type)
+ if (MAYBE_CLASS_TYPE_P (type)
&& CLASSTYPE_TEMPLATE_INFO (type)
&& !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
{
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
no partial specializations of functions. Therefore, if
the type of DECL does not match FN, there is no
match. */
- if (tsk == tsk_template
- && !compparms (fn_arg_types, decl_arg_types))
- continue;
+ if (tsk == tsk_template)
+ {
+ if (compparms (fn_arg_types, decl_arg_types))
+ candidates = tree_cons (NULL_TREE, fn, candidates);
+ continue;
+ }
/* See whether this function might be a specialization of this
template. */
if (parameter_packs)
{
- error ("parameter packs not expanded with `...':");
+ error ("parameter packs not expanded with %<...%>:");
while (parameter_packs)
{
tree pack = TREE_VALUE (parameter_packs);
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
- TREE_INVARIANT (t) = TREE_INVARIANT (decl);
TREE_READONLY (t) = TREE_READONLY (decl);
return t;
VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
list = VEC_index (tree, canonical_template_parms, idx);
- while (list && !cp_comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+ while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
list = TREE_CHAIN (list);
if (list)
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
- TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
/* A template parameter is not modifiable. */
TREE_CONSTANT (parm) = 1;
- TREE_INVARIANT (parm) = 1;
TREE_READONLY (parm) = 1;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
- TREE_INVARIANT (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
if (parm && TREE_CODE (parm) == TEMPLATE_DECL)
{
- t = make_aggr_type (TEMPLATE_TEMPLATE_PARM);
+ t = cxx_make_type (TEMPLATE_TEMPLATE_PARM);
/* This is for distinguishing between real templates and template
template parameters */
TREE_TYPE (parm) = t;
}
else
{
- t = make_aggr_type (TEMPLATE_TYPE_PARM);
+ t = cxx_make_type (TEMPLATE_TYPE_PARM);
/* parm is either IDENTIFIER_NODE or NULL_TREE. */
decl = build_decl (TYPE_DECL, parm, t);
}
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
&& ANON_AGGRNAME_P (DECL_NAME (decl)))
- error ("template class without a name");
+ {
+ error ("template class without a name");
+ return error_mark_node;
+ }
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (DECL_DESTRUCTOR_P (decl))
return expr;
}
+/* Subroutine of coerce_template_template_parms, which returns 1 if
+ PARM_PARM and ARG_PARM match using the rule for the template
+ parameters of template template parameters. Both PARM and ARG are
+ template parameters; the rest of the arguments are the same as for
+ coerce_template_template_parms.
+ */
+static int
+coerce_template_template_parm (tree parm,
+ tree arg,
+ tsubst_flags_t complain,
+ tree in_decl,
+ tree outer_args)
+{
+ if (arg == NULL_TREE || arg == error_mark_node
+ || parm == NULL_TREE || parm == error_mark_node)
+ return 0;
+
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 0;
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ /* We encounter instantiations of templates like
+ template <template <template <class> class> class TT>
+ class C; */
+ {
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (!coerce_template_template_parms
+ (parmparm, argparm, complain, in_decl, outer_args))
+ return 0;
+ }
+ /* Fall through. */
+
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
+ && !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+ break;
+
+ case PARM_DECL:
+ /* The tsubst call is used to handle cases such as
+
+ template <int> class C {};
+ template <class T, template <T> class TT> class D {};
+ D<int, C> d;
+
+ i.e. the parameter list of TT depends on earlier parameters. */
+ if (!dependent_type_p (TREE_TYPE (arg))
+ && !same_type_p
+ (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
+ TREE_TYPE (arg)))
+ return 0;
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
+ && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ /* Argument is a parameter pack but parameter is not. */
+ return 0;
+
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return 1;
+}
+
/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for
template template parameters. Both PARM_PARMS and ARG_PARMS are
{
int nparms, nargs, i;
tree parm, arg;
+ int variadic_p = 0;
gcc_assert (TREE_CODE (parm_parms) == TREE_VEC);
gcc_assert (TREE_CODE (arg_parms) == TREE_VEC);
nparms = TREE_VEC_LENGTH (parm_parms);
nargs = TREE_VEC_LENGTH (arg_parms);
- if (nargs != nparms)
+ /* Determine whether we have a parameter pack at the end of the
+ template template parameter's template parameter list. */
+ if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
+ {
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
+
+ switch (TREE_CODE (parm))
+ {
+ case TEMPLATE_DECL:
+ case TYPE_DECL:
+ if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+ variadic_p = 1;
+ break;
+
+ case PARM_DECL:
+ if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ variadic_p = 1;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ if (nargs != nparms
+ && !(variadic_p && nargs >= nparms - 1))
return 0;
- for (i = 0; i < nparms; ++i)
+ /* Check all of the template parameters except the parameter pack at
+ the end (if any). */
+ for (i = 0; i < nparms - variadic_p; ++i)
{
if (TREE_VEC_ELT (parm_parms, i) == error_mark_node
|| TREE_VEC_ELT (arg_parms, i) == error_mark_node)
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
- if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
- return 0;
-
- if (TREE_CODE (arg) != TREE_CODE (parm))
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
return 0;
- switch (TREE_CODE (parm))
- {
- case TEMPLATE_DECL:
- /* We encounter instantiations of templates like
- template <template <template <class> class> class TT>
- class C; */
- {
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (!coerce_template_template_parms
- (parmparm, argparm, complain, in_decl, outer_args))
- return 0;
- }
- /* Fall through. */
-
- case TYPE_DECL:
- if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm))
- != TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
-
- case PARM_DECL:
- /* The tsubst call is used to handle cases such as
-
- template <int> class C {};
- template <class T, template <T> class TT> class D {};
- D<int, C> d;
+ }
- i.e. the parameter list of TT depends on earlier parameters. */
- if (!dependent_type_p (TREE_TYPE (arg))
- && !same_type_p
- (tsubst (TREE_TYPE (parm), outer_args, complain, in_decl),
- TREE_TYPE (arg)))
- return 0;
+ if (variadic_p)
+ {
+ /* Check each of the template parameters in the template
+ argument against the template parameter pack at the end of
+ the template template parameter. */
+ if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
+ return 0;
- if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
- != TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg)))
- /* One is a parameter pack, the other is not. */
- return 0;
- break;
+ parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
- default:
- gcc_unreachable ();
- }
+ for (; i < nargs; ++i)
+ {
+ if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
+ continue;
+
+ arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
+
+ if (!coerce_template_template_parm (parm, arg, complain, in_decl,
+ outer_args))
+ return 0;
+ }
}
+
return 1;
}
template_template_parm_bindings_ok_p (tree tparms, tree targs)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
+ bool ret = true;
+
+ /* We're dealing with template parms in this process. */
+ ++processing_template_decl;
targs = INNERMOST_TEMPLATE_ARGS (targs);
tf_none,
tparm,
targs))
- return false;
+ {
+ ret = false;
+ goto out;
+ }
}
}
}
- /* Everything is okay. */
- return true;
+ out:
+
+ --processing_template_decl;
+ return ret;
}
/* Convert the indicated template ARG as necessary to match the
if (template)
context = DECL_CONTEXT (template);
}
- else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
+ else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
{
tree type = TREE_TYPE (d1);
}
}
else if (TREE_CODE (d1) == ENUMERAL_TYPE
- || (TYPE_P (d1) && IS_AGGR_TYPE (d1)))
+ || (TYPE_P (d1) && MAYBE_CLASS_TYPE_P (d1)))
{
template = TYPE_TI_TEMPLATE (d1);
d1 = DECL_NAME (template);
}
else
{
- t = make_aggr_type (TREE_CODE (template_type));
+ t = make_class_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
{
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
- TREE_VALUE (t)
- = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
+ /* If the first attribute argument is an identifier, don't
+ pass it through tsubst. Attributes like mode, format,
+ cleanup and several target specific attributes expect it
+ unmodified. */
+ if (TREE_VALUE (t)
+ && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
+ && TREE_VALUE (TREE_VALUE (t))
+ && (TREE_CODE (TREE_VALUE (TREE_VALUE (t)))
+ == IDENTIFIER_NODE))
+ {
+ tree chain
+ = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
+ in_decl,
+ /*integral_constant_expression_p=*/false);
+ if (chain != TREE_CHAIN (TREE_VALUE (t)))
+ TREE_VALUE (t)
+ = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
+ chain);
+ }
+ else
+ TREE_VALUE (t)
+ = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
*q = t;
q = &TREE_CHAIN (t);
}
else
{
tree r = TREE_TYPE (TREE_VALUE (arg_types));
- if (! IS_AGGR_TYPE (r))
+ if (! MAYBE_CLASS_TYPE_P (r))
{
/* [temp.deduct]
message to avoid spewing a ton of messages during a
single bad template instantiation. */
if (complain & tf_error
-#ifdef USE_MAPPED_LOCATION
- && last_loc != input_location
-#else
- && (last_loc.line != input_line
- || last_loc.file != input_filename)
-#endif
- )
+ && last_loc != input_location)
{
if (TREE_CODE (type) == VOID_TYPE)
error ("forming reference to void");
case OFFSET_TYPE:
{
r = tsubst (TYPE_OFFSET_BASETYPE (t), args, complain, in_decl);
- if (r == error_mark_node || !IS_AGGR_TYPE (r))
+ if (r == error_mark_node || !MAYBE_CLASS_TYPE_P (r))
{
/* [temp.deduct]
if (ctx == error_mark_node || f == error_mark_node)
return error_mark_node;
- if (!IS_AGGR_TYPE (ctx))
+ if (!MAYBE_CLASS_TYPE_P (ctx))
{
if (complain & tf_error)
error ("%qT is not a class, struct, or union type", ctx);
/* We only want to compute the number of arguments. */
tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
complain, in_decl);
+ int len = 0;
+
+ if (TREE_CODE (expanded) == TREE_VEC)
+ len = TREE_VEC_LENGTH (expanded);
+
if (expanded == error_mark_node)
return error_mark_node;
- return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
+ else if (PACK_EXPANSION_P (expanded)
+ || (TREE_CODE (expanded) == TREE_VEC
+ && len > 0
+ && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+ {
+ if (TREE_CODE (expanded) == TREE_VEC)
+ expanded = TREE_VEC_ELT (expanded, len - 1);
+
+ if (TYPE_P (expanded))
+ return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ else
+ return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+ complain & tf_error);
+ }
+ else
+ return build_int_cst (size_type_node, len);
}
/* Fall through */
switch (OMP_CLAUSE_CODE (nc))
{
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_STMT (oc))
+ {
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list ();
+ tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_LASTPRIVATE_STMT (nc)
+ = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc));
+ }
+ /* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_COLLAPSE:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
break;
default:
gcc_unreachable ();
#undef RECUR
}
+/* Substitute one OMP_FOR iterator. */
+
+static void
+tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
+ tree condv, tree incrv, tree *clauses,
+ tree args, tsubst_flags_t complain, tree in_decl,
+ bool integral_constant_expression_p)
+{
+#define RECUR(NODE) \
+ tsubst_expr ((NODE), args, complain, in_decl, \
+ integral_constant_expression_p)
+ tree decl, init, cond, incr;
+
+ init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
+ gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+ decl = RECUR (TREE_OPERAND (init, 0));
+ init = TREE_OPERAND (init, 1);
+ gcc_assert (!type_dependent_expression_p (decl));
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i));
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ if (TREE_CODE (incr) == MODIFY_EXPR)
+ incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR,
+ RECUR (TREE_OPERAND (incr, 1)),
+ complain);
+ else
+ incr = RECUR (incr);
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+ return;
+ }
+
+ if (init && TREE_CODE (init) != DECL_EXPR)
+ {
+ tree c;
+ for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be firstprivate", decl);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("iteration variable %qD should not be reduction", decl);
+ }
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ c = finish_omp_clauses (c);
+ if (c)
+ {
+ OMP_CLAUSE_CHAIN (c) = *clauses;
+ *clauses = c;
+ }
+ }
+ }
+ cond = TREE_VEC_ELT (OMP_FOR_COND (t), i);
+ if (COMPARISON_CLASS_P (cond))
+ cond = build2 (TREE_CODE (cond), boolean_type_node,
+ RECUR (TREE_OPERAND (cond, 0)),
+ RECUR (TREE_OPERAND (cond, 1)));
+ else
+ cond = RECUR (cond);
+ incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i);
+ switch (TREE_CODE (incr))
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ incr = build2 (TREE_CODE (incr), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)), NULL_TREE);
+ break;
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree rhs = TREE_OPERAND (incr, 1);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ case MODOP_EXPR:
+ if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree lhs = RECUR (TREE_OPERAND (incr, 0));
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs,
+ build2 (TREE_CODE (TREE_OPERAND (incr, 1)),
+ TREE_TYPE (decl), lhs,
+ RECUR (TREE_OPERAND (incr, 2))));
+ }
+ else if (TREE_CODE (TREE_OPERAND (incr, 1)) == NOP_EXPR
+ && (TREE_CODE (TREE_OPERAND (incr, 2)) == PLUS_EXPR
+ || (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR)))
+ {
+ tree rhs = TREE_OPERAND (incr, 2);
+ incr = build2 (MODIFY_EXPR, TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (incr, 0)),
+ build2 (TREE_CODE (rhs), TREE_TYPE (decl),
+ RECUR (TREE_OPERAND (rhs, 0)),
+ RECUR (TREE_OPERAND (rhs, 1))));
+ }
+ else
+ incr = RECUR (incr);
+ break;
+ default:
+ incr = RECUR (incr);
+ break;
+ }
+
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+#undef RECUR
+}
+
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
= OMP_PARALLEL_COMBINED (t);
break;
+ case OMP_TASK:
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ args, complain, in_decl);
+ stmt = begin_omp_task ();
+ RECUR (OMP_TASK_BODY (t));
+ finish_omp_task (tmp, stmt);
+ break;
+
case OMP_FOR:
{
- tree clauses, decl, init, cond, incr, body, pre_body;
+ tree clauses, body, pre_body;
+ tree declv, initv, condv, incrv;
+ int i;
clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
args, complain, in_decl);
- init = OMP_FOR_INIT (t);
- gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- decl = RECUR (TREE_OPERAND (init, 0));
- init = RECUR (TREE_OPERAND (init, 1));
- cond = RECUR (OMP_FOR_COND (t));
- incr = RECUR (OMP_FOR_INCR (t));
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
stmt = begin_omp_structured_block ();
+ for (i = 0; i < TREE_VEC_LENGTH (initv); i++)
+ if (TREE_VEC_ELT (initv, i) == NULL
+ || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR)
+ TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i));
+ else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i))))
+ {
+ tree init = RECUR (TREE_VEC_ELT (initv, i));
+ gcc_assert (init == TREE_VEC_ELT (declv, i));
+ TREE_VEC_ELT (initv, i) = NULL_TREE;
+ }
+ else
+ {
+ tree decl_expr = TREE_VEC_ELT (initv, i);
+ tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
+ gcc_assert (init != NULL);
+ TREE_VEC_ELT (initv, i) = RECUR (init);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
+ RECUR (decl_expr);
+ DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init;
+ }
+
pre_body = push_stmt_list ();
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body,
- pre_body);
- if (t)
- OMP_FOR_CLAUSES (t) = clauses;
+ t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
+ body, pre_body, clauses);
add_stmt (finish_omp_structured_block (stmt));
}
r = convert_from_reference (r);
}
else
- r = build_x_indirect_ref (r, "unary *");
+ r = build_x_indirect_ref (r, "unary *", complain);
return r;
}
if (integral_constant_expression_p
&& !cast_valid_in_integral_constant_expression_p (type))
{
- error ("a cast to a type other than an integral or "
- "enumeration type cannot appear in a constant-expression");
+ if (complain & tf_error)
+ error ("a cast to a type other than an integral or "
+ "enumeration type cannot appear in a constant-expression");
return error_mark_node;
}
switch (TREE_CODE (t))
{
case CAST_EXPR:
- return build_functional_cast (type, op);
+ return build_functional_cast (type, op, complain);
case REINTERPRET_CAST_EXPR:
- return build_reinterpret_cast (type, op);
+ return build_reinterpret_cast (type, op, complain);
case CONST_CAST_EXPR:
- return build_const_cast (type, op);
+ return build_const_cast (type, op, complain);
case DYNAMIC_CAST_EXPR:
- return build_dynamic_cast (type, op);
+ return build_dynamic_cast (type, op, complain);
case STATIC_CAST_EXPR:
- return build_static_cast (type, op);
+ return build_static_cast (type, op, complain);
default:
gcc_unreachable ();
}
case POSTINCREMENT_EXPR:
op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
args, complain, in_decl);
- return build_x_unary_op (TREE_CODE (t), op1);
+ return build_x_unary_op (TREE_CODE (t), op1, complain);
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case UNARY_PLUS_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
- return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
+ return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)),
+ complain);
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
in_decl);
if (TREE_CODE (op1) == LABEL_DECL)
return finish_label_address_expr (DECL_NAME (op1));
- return build_x_unary_op (ADDR_EXPR, op1);
+ return build_x_unary_op (ADDR_EXPR, op1, complain);
case PLUS_EXPR:
case MINUS_EXPR:
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL);
+ /*overloaded_p=*/NULL,
+ complain);
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
- {
- /* We only want to compute the number of arguments. */
- tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
- if (expanded == error_mark_node)
- return error_mark_node;
- return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
- }
+ return tsubst_copy (t, args, complain, in_decl);
/* Fall through */
case ALIGNOF_EXPR:
--skip_evaluation;
}
if (TYPE_P (op1))
- return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), true);
+ return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
else
- return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t));
+ return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
case MODOP_EXPR:
{
tree r = build_x_modify_expr
(RECUR (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ RECUR (TREE_OPERAND (t, 2)),
+ complain);
/* TREE_NO_WARNING must be set if either the expression was
parenthesized or it uses an operator such as >>= rather
than plain assignment. In the former case, it was already
RECUR (TREE_OPERAND (t, 1)),
RECUR (TREE_OPERAND (t, 2)),
init,
- NEW_EXPR_USE_GLOBAL (t));
+ NEW_EXPR_USE_GLOBAL (t),
+ complain);
}
case DELETE_EXPR:
case COMPOUND_EXPR:
return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)));
+ RECUR (TREE_OPERAND (t, 1)),
+ complain);
case CALL_EXPR:
{
if (!BASELINK_P (TREE_OPERAND (function, 1)))
return finish_call_expr (function, call_args,
/*disallow_virtual=*/false,
- /*koenig_p=*/false);
+ /*koenig_p=*/false,
+ complain);
else
return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
- /*fn_p=*/NULL));
+ /*fn_p=*/NULL,
+ complain));
}
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p,
- koenig_p);
+ koenig_p,
+ complain);
}
case COND_EXPR:
return build_x_conditional_expr
(RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)));
+ RECUR (TREE_OPERAND (t, 2)),
+ complain);
case PSEUDO_DTOR_EXPR:
return finish_pseudo_destructor_expr
return finish_non_static_data_member (member, object, NULL_TREE);
return finish_class_member_access_expr (object, member,
- /*template_p=*/false);
+ /*template_p=*/false,
+ complain);
}
case THROW_EXPR:
/* We do not want to process the index of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
- process_index_p = !(type && IS_AGGR_TYPE (type));
+ process_index_p = !(type && MAYBE_CLASS_TYPE_P (type));
n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
newlen = VEC_length (constructor_elt, n);
tree rval = NULL_TREE;
tree binfo;
- gcc_assert (IS_AGGR_TYPE_CODE (TREE_CODE (arg)));
+ gcc_assert (RECORD_OR_UNION_CODE_P (TREE_CODE (arg)));
binfo = TYPE_BINFO (complete_type (arg));
if (!binfo)
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
- tree argtmplvec
- = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
+ tree parm_parms
+ = DECL_INNERMOST_TEMPLATE_PARMS
+ (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
int i, len;
int parm_variadic_p = 0;
Here, if Lvalue_proxy is permitted to bind to View, then
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
- if (coerce_template_parms (argtmplvec, parmvec,
+ if (coerce_template_parms (parm_parms,
+ argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
processing_template_decl++;
- while (len--)
+ while (len--
+ /* Stop when an ellipsis is seen. */
+ && args1 != NULL_TREE && args2 != NULL_TREE)
{
tree arg1 = TREE_VALUE (args1);
tree arg2 = TREE_VALUE (args2);
args1 = TREE_CHAIN (args1);
args2 = TREE_CHAIN (args2);
-
- /* Stop when an ellipsis is seen. */
- if (args1 == NULL_TREE || args2 == NULL_TREE)
- break;
}
processing_template_decl--;
{
tree storage = *(tree *) data;
- if (IS_AGGR_TYPE (entry->type)
+ if (MAYBE_CLASS_TYPE_P (entry->type)
&& !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
}
= tsubst_pack_expansion (expr, argvec,
tf_warning_or_error,
NULL_TREE);
+ if (expanded_exprs == error_mark_node)
+ continue;
/* Prepend each of the expanded expressions to the
corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
|| any_dependent_template_arguments_p (args));
}
+/* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors
+ is dependent. */
+
+bool
+dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv)
+{
+ int i;
+
+ if (!processing_template_decl)
+ return false;
+
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
+ {
+ tree decl = TREE_VEC_ELT (declv, i);
+ tree init = TREE_VEC_ELT (initv, i);
+ tree cond = TREE_VEC_ELT (condv, i);
+ tree incr = TREE_VEC_ELT (incrv, i);
+
+ if (type_dependent_expression_p (decl))
+ return true;
+
+ if (init && type_dependent_expression_p (init))
+ return true;
+
+ if (type_dependent_expression_p (cond))
+ return true;
+
+ if (COMPARISON_CLASS_P (cond)
+ && (type_dependent_expression_p (TREE_OPERAND (cond, 0))
+ || type_dependent_expression_p (TREE_OPERAND (cond, 1))))
+ return true;
+
+ if (TREE_CODE (incr) == MODOP_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0))
+ || type_dependent_expression_p (TREE_OPERAND (incr, 2)))
+ return true;
+ }
+ else if (type_dependent_expression_p (incr))
+ return true;
+ else if (TREE_CODE (incr) == MODIFY_EXPR)
+ {
+ if (type_dependent_expression_p (TREE_OPERAND (incr, 0)))
+ return true;
+ else if (BINARY_CLASS_P (TREE_OPERAND (incr, 1)))
+ {
+ tree t = TREE_OPERAND (incr, 1);
+ if (type_dependent_expression_p (TREE_OPERAND (t, 0))
+ || type_dependent_expression_p (TREE_OPERAND (t, 1)))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
TYPENAME_TYPE corresponds. Returns the original TYPENAME_TYPE if
no such TYPE can be found. Note that this function peers inside