#include "rtl.h"
#include "timevar.h"
#include "tree-iterator.h"
+#include "vecprim.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
static int template_header_count;
static GTY(()) tree saved_trees;
-static GTY(()) varray_type inline_parm_levels;
-static size_t inline_parm_levels_used;
+static VEC(int,heap) *inline_parm_levels;
static GTY(()) tree current_tinst_level;
static tree try_class_unification (tree, tree, tree, tree);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
-static tree determine_specialization (tree, tree, tree *, int, int);
static int template_args_equal (tree, tree);
static void tsubst_default_arguments (tree);
static tree for_each_template_parm_r (tree *, int *, void *);
/* Remember how many levels of template parameters we pushed so that
we can pop them later. */
- if (!inline_parm_levels)
- VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels");
- if (inline_parm_levels_used == inline_parm_levels->num_elements)
- VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used);
- VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels;
- ++inline_parm_levels_used;
+ VEC_safe_push (int, heap, inline_parm_levels, levels);
}
/* Undo the effects of maybe_begin_member_template_processing. */
maybe_end_member_template_processing (void)
{
int i;
+ int last;
- if (!inline_parm_levels_used)
+ if (VEC_length (int, inline_parm_levels) == 0)
return;
- --inline_parm_levels_used;
- for (i = 0;
- i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used);
- ++i)
+ last = VEC_pop (int, inline_parm_levels);
+ for (i = 0; i < last; ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
template classes that appeared in the name of the function. See
check_explicit_specialization for a more accurate description.
+ TSK indicates what kind of template declaration (if any) is being
+ declared. TSK_TEMPLATE indicates that the declaration given by
+ DECL, though a FUNCTION_DECL, has template parameters, and is
+ therefore a template function.
+
The template args (those explicitly specified and those deduced)
are output in a newly created vector *TARGS_OUT.
tree decl,
tree* targs_out,
int need_member_template,
- int template_count)
+ int template_count,
+ tmpl_spec_kind tsk)
{
tree fns;
tree targs;
(current_template_parms))))
continue;
+ /* Function templates cannot be specializations; there are
+ no partial specializations of functions. Therefore, if
+ the type of DECL does not match FN, there is no
+ match. */
+ if (tsk == tsk_template)
+ {
+ if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ decl_arg_types))
+ candidates = tree_cons (NULL_TREE, fn, candidates);
+ continue;
+ }
+
/* See whether this function might be a specialization of this
template. */
targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
/* We have one, and exactly one, match. */
if (candidates)
{
+ tree fn = TREE_VALUE (candidates);
+ /* DECL is a re-declaration of a template function. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return fn;
/* It was a specialization of an ordinary member function in a
template class. */
- *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
- return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+ *targs_out = copy_node (DECL_TI_ARGS (fn));
+ return DECL_TI_TEMPLATE (fn);
}
/* It was a specialization of a template. */
tmpl = determine_specialization (declarator, decl,
&targs,
member_specialization,
- template_count);
+ template_count,
+ tsk);
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
revert_static_member_fn (decl);
/* If this is a specialization of a member template of a
- template class. In we want to return the TEMPLATE_DECL,
- not the specialization of it. */
+ template class, we want to return the TEMPLATE_DECL, not
+ the specialization of it. */
if (tsk == tsk_template)
{
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
return TEMPLATE_PARM_DESCENDANTS (index);
}
-/* Process information from new template parameter NEXT and append it to the
+/* Process information from new template parameter PARM and append it to the
LIST being built. This new parameter is a non-type parameter iff
IS_NON_TYPE is true. */
tree
-process_template_parm (tree list, tree next, bool is_non_type)
+process_template_parm (tree list, tree parm, bool is_non_type)
{
- tree parm;
tree decl = 0;
tree defval;
int idx;
- parm = next;
gcc_assert (TREE_CODE (parm) == TREE_LIST);
defval = TREE_PURPOSE (parm);
SET_DECL_TEMPLATE_PARM_P (parm);
- /* [temp.param]
+ if (TREE_TYPE (parm) == error_mark_node)
+ TREE_TYPE (parm) = void_type_node;
+ else
+ {
+ /* [temp.param]
- The top-level cv-qualifiers on the template-parameter are
- ignored when determining its type. */
- TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+ The top-level cv-qualifiers on the template-parameter are
+ ignored when determining its type. */
+ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+ if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
+ TREE_TYPE (parm) = void_type_node;
+ }
/* A template parameter is not modifiable. */
TREE_CONSTANT (parm) = 1;
TREE_INVARIANT (parm) = 1;
TREE_READONLY (parm) = 1;
- if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
- TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
TREE_INVARIANT (decl) = 1;
template. ... Template allocation functions shall
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
- return decl;
+ return error_mark_node;
}
}
else if (DECL_IMPLICIT_TYPEDEF_P (decl)
instantiated -- but here we need the resolved form so that we can
convert the argument. */
expr = fold_non_dependent_expr (expr);
+ if (error_operand_p (expr))
+ return error_mark_node;
expr_type = TREE_TYPE (expr);
/* HACK: Due to double coercion, we can get a
warning messages are issued under control of COMPLAIN.
If REQUIRE_ALL_ARGS is false, argument deduction will be performed
- for arugments not specified in ARGS. Otherwise, if
+ for arguments not specified in ARGS. Otherwise, if
USE_DEFAULT_ARGS is true, default arguments will be used to fill in
unspecified arguments. If REQUIRE_ALL_ARGS is true, but
USE_DEFAULT_ARGS is false, then all arguments must be specified in
tmpl = determine_specialization (template_id, new_friend,
&new_args,
/*need_member_template=*/0,
- TREE_VEC_LENGTH (args));
+ TREE_VEC_LENGTH (args),
+ tsk_none);
return instantiate_template (tmpl, new_args, tf_error);
}
old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
pop_nested_namespace (ns);
+ if (old_decl == error_mark_node)
+ return error_mark_node;
+
if (old_decl != new_friend)
{
/* This new friend declaration matched an existing
case, the instantiation of the template class will cause the
injection of this template into the global scope. */
tmpl = tsubst (friend_tmpl, args, tf_warning_or_error, NULL_TREE);
+ if (tmpl == error_mark_node)
+ return error_mark_node;
/* The new TMPL is not an instantiation of anything, so we
forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
if (TREE_CODE (t) == TEMPLATE_DECL)
--processing_template_decl;
set_current_access_from_decl (r);
- grok_special_member_properties (r);
finish_member_declaration (r);
}
else
}
push_deferring_access_checks(dk_no_deferred);
+ /* The default argument expression may cause implicitly defined
+ member functions to be synthesized, which will result in garbage
+ collection. We must treat this situation as if we were within
+ the body of function so as to avoid collecting live data on the
+ stack. */
+ ++function_depth;
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_warning_or_error, NULL_TREE);
+ --function_depth;
pop_deferring_access_checks();
/* Restore the "this" pointer. */
decl = tsubst (decl, args, complain, in_decl);
if (decl != error_mark_node)
{
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done
}
else
{
+ tree compound_stmt = NULL_TREE;
+
if (FN_TRY_BLOCK_P (t))
- stmt = begin_function_try_block ();
+ stmt = begin_function_try_block (&compound_stmt);
else
stmt = begin_try_block ();
tsubst_expr (TRY_HANDLERS (t), args, complain, in_decl);
if (FN_TRY_BLOCK_P (t))
- finish_function_handler_sequence (stmt);
+ finish_function_handler_sequence (stmt, compound_stmt);
else
finish_handler_sequence (stmt);
}
args, complain, in_decl);
stmt = begin_omp_parallel ();
tsubst_expr (OMP_PARALLEL_BODY (t), args, complain, in_decl);
- finish_omp_parallel (tmp, stmt);
+ OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
+ = OMP_PARALLEL_COMBINED (t);
break;
case OMP_FOR:
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
- qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+ qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
+ /*fn_p=*/NULL));
}
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p,
tree result = NULL_TREE;
int extern_p = 0;
- if (!decl)
+ if (!decl || decl == error_mark_node)
/* An error occurred, for which grokdeclarator has already issued
an appropriate message. */
return;
init = tsubst_expr (DECL_INITIAL (code_pattern),
args,
tf_warning_or_error, NULL_TREE);
- DECL_INITIAL (d) = init;
cp_finish_decl (d, init, /*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING);
if (TREE_CODE (d) == VAR_DECL)
{
+ tree init;
+
/* Clear out DECL_RTL; whatever was there before may not be right
since we've reset the type of the declaration. */
SET_DECL_RTL (d, NULL_RTX);
DECL_IN_AGGR_P (d) = 0;
+ /* The initializer is placed in DECL_INITIAL by
+ regenerate_decl_from_template. Pull it out so that
+ finish_decl can process it. */
+ init = DECL_INITIAL (d);
+ DECL_INITIAL (d) = NULL_TREE;
+ DECL_INITIALIZED_P (d) = 0;
+
/* Clear DECL_EXTERNAL so that cp_finish_decl will process the
initializer. That function will defer actual emission until
we have a chance to determine linkage. */
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- finish_decl (d, DECL_INITIAL (d), NULL_TREE);
+ finish_decl (d, init, NULL_TREE);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
if (!args)
return false;
+ if (args == error_mark_node)
+ return true;
for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
{
return expr;
/* Preserve OVERLOADs; the functions must be available to resolve
types. */
- inner_expr = (TREE_CODE (expr) == ADDR_EXPR ?
- TREE_OPERAND (expr, 0) :
- TREE_CODE (expr) == COMPONENT_REF ?
- TREE_OPERAND (expr, 1) : expr);
+ inner_expr = expr;
+ if (TREE_CODE (inner_expr) == ADDR_EXPR)
+ inner_expr = TREE_OPERAND (inner_expr, 0);
+ if (TREE_CODE (inner_expr) == COMPONENT_REF)
+ inner_expr = TREE_OPERAND (inner_expr, 1);
if (is_overloaded_fn (inner_expr)
|| TREE_CODE (inner_expr) == OFFSET_REF)
return expr;