re PR c++/31439 (ICE with variadic template and broken specialization)
2007-11-06 Douglas Gregor <doug.gregor@gmail.com> PR c++/31439 PR c++/32114 PR c++/32115 PR c++/32125 PR c++/32126 PR c++/32127 PR c++/32128 PR c++/32253 PR c++/32566 * typeck.c (check_return_expr): Pass address of retval to check_for_bare_parameter_packs. * class.c (build_base_field): Tolerate bases that have no layout due to errors. (end_of_base): Ditto. * tree.c (canonical_type_variant): Be careful with ERROR_MARK_NODE. * cp-tree.h (check_for_bare_parameter_packs): Now accepts a tree*. * pt.c (find_parameter_pack_data): Add set_packs_to_error field, which states whether parameter packs should be replaced with ERROR_MARK_NODE. (find_parameter_packs_r): Pass addresses to cp_walk_tree wherever possible. If set_packs_to_error is set true, replace the parameter pack with ERROR_MARK_NODE. Manage our own pointer sets. (uses_parameter_packs): Don't set parameter packs to ERROR_MARK_NODE. (check_for_bare_parameter_packs): Now takes a pointer to a tree, which may be modified (if it is a parameter pack). Instructs find_parameter_packs_r to replace parameter packs with ERROR_MARK_NODE (so that they won't cause errors later on). (process_template_parm): Pass pointer to check_for_bare_parameter_packs. (process_partial_specialization): Replace pack expansions before the end of the template argument list with ERROR_MARK_NODE. (push_template_decl_real): Pass pointer to check_for_bare_parameter_packs. Replace parameter packs not at the end of the template parameter list with ERROR_MARK_NODE. (convert_template_argument): Be more careful about using DECL_NAME on only declarations. (unify): Can't unify against ERROR_MARK_NODE. * semantics.c (finish_cond): Pass pointer to check_for_bare_parameter_packs. (finish_expr_stmt): Ditto. (finish_for_expr): Ditto. (finish_switch_cond): Pass pointer to check_for_bare_parameter_packs, and call it before we put the condition into the statement. (finish_mem_initializers): Pass pointer to check_for_bare_parameter_packs. (finish_member_declaration): Ditto. * parser.c (cp_parser_base_clause): Ditto. 2007-11-06 Douglas Gregor <doug.gregor@gmail.com> * testsuite/g++.dg/parser/crash36.C: Tweak expected errors. * testsuite/g++.dg/cpp0x/pr31439.C: New. * testsuite/g++.dg/cpp0x/pr32114.C: New. * testsuite/g++.dg/cpp0x/pr32115.C: New. * testsuite/g++.dg/cpp0x/pr32125.C: New. * testsuite/g++.dg/cpp0x/pr32126.C: New. * testsuite/g++.dg/cpp0x/pr32127.C: New. * testsuite/g++.dg/cpp0x/pr32128.C: New. * testsuite/g++.dg/cpp0x/pr32253.C: New. * testsuite/g++.dg/cpp0x/pr32566.C: New. * testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors. * testsuite/g++.dg/cpp0x/pr31438.C: Ditto. * testsuite/g++.dg/cpp0x/variadic81.C: Ditto. * testsuite/g++.dg/cpp0x/pr31432.C: Ditto. * testsuite/g++.dg/cpp0x/pr31442.C: Ditto. From-SVN: r129928
This commit is contained in:
parent
3de36a09ac
commit
1ad8aeeb96
@ -1,3 +1,57 @@
|
||||
2007-11-06 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
PR c++/31439
|
||||
PR c++/32114
|
||||
PR c++/32115
|
||||
PR c++/32125
|
||||
PR c++/32126
|
||||
PR c++/32127
|
||||
PR c++/32128
|
||||
PR c++/32253
|
||||
PR c++/32566
|
||||
* typeck.c (check_return_expr): Pass address of retval to
|
||||
check_for_bare_parameter_packs.
|
||||
* class.c (build_base_field): Tolerate bases that have no layout
|
||||
due to errors.
|
||||
(end_of_base): Ditto.
|
||||
* tree.c (canonical_type_variant): Be careful with
|
||||
ERROR_MARK_NODE.
|
||||
* cp-tree.h (check_for_bare_parameter_packs): Now accepts a
|
||||
tree*.
|
||||
* pt.c (find_parameter_pack_data): Add set_packs_to_error field,
|
||||
which states whether parameter packs should be replaced with
|
||||
ERROR_MARK_NODE.
|
||||
(find_parameter_packs_r): Pass addresses to cp_walk_tree wherever
|
||||
possible. If set_packs_to_error is set true, replace the parameter
|
||||
pack with ERROR_MARK_NODE. Manage our own pointer sets.
|
||||
(uses_parameter_packs): Don't set parameter packs to
|
||||
ERROR_MARK_NODE.
|
||||
(check_for_bare_parameter_packs): Now takes a pointer to a tree,
|
||||
which may be modified (if it is a parameter pack). Instructs
|
||||
find_parameter_packs_r to replace parameter packs with
|
||||
ERROR_MARK_NODE (so that they won't cause errors later on).
|
||||
(process_template_parm): Pass pointer to
|
||||
check_for_bare_parameter_packs.
|
||||
(process_partial_specialization): Replace pack expansions before
|
||||
the end of the template argument list with ERROR_MARK_NODE.
|
||||
(push_template_decl_real): Pass pointer to
|
||||
check_for_bare_parameter_packs. Replace parameter packs not at the
|
||||
end of the template parameter list with ERROR_MARK_NODE.
|
||||
(convert_template_argument): Be more careful about using DECL_NAME
|
||||
on only declarations.
|
||||
(unify): Can't unify against ERROR_MARK_NODE.
|
||||
* semantics.c (finish_cond): Pass pointer to
|
||||
check_for_bare_parameter_packs.
|
||||
(finish_expr_stmt): Ditto.
|
||||
(finish_for_expr): Ditto.
|
||||
(finish_switch_cond): Pass pointer to
|
||||
check_for_bare_parameter_packs, and call it before we put the
|
||||
condition into the statement.
|
||||
(finish_mem_initializers): Pass pointer to
|
||||
check_for_bare_parameter_packs.
|
||||
(finish_member_declaration): Ditto.
|
||||
* parser.c (cp_parser_base_clause): Ditto.
|
||||
|
||||
2007-11-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/33168
|
||||
|
@ -3613,21 +3613,24 @@ build_base_field (record_layout_info rli, tree binfo,
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
DECL_IGNORED_P (decl) = 1;
|
||||
DECL_FIELD_CONTEXT (decl) = t;
|
||||
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
|
||||
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
|
||||
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
|
||||
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
|
||||
DECL_MODE (decl) = TYPE_MODE (basetype);
|
||||
DECL_FIELD_IS_BASE (decl) = 1;
|
||||
if (CLASSTYPE_AS_BASE (basetype))
|
||||
{
|
||||
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
|
||||
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
|
||||
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
|
||||
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
|
||||
DECL_MODE (decl) = TYPE_MODE (basetype);
|
||||
DECL_FIELD_IS_BASE (decl) = 1;
|
||||
|
||||
/* Try to place the field. It may take more than one try if we
|
||||
have a hard time placing the field without putting two
|
||||
objects of the same type at the same address. */
|
||||
layout_nonempty_base_or_field (rli, decl, binfo, offsets);
|
||||
/* Add the new FIELD_DECL to the list of fields for T. */
|
||||
TREE_CHAIN (decl) = *next_field;
|
||||
*next_field = decl;
|
||||
next_field = &TREE_CHAIN (decl);
|
||||
/* Try to place the field. It may take more than one try if we
|
||||
have a hard time placing the field without putting two
|
||||
objects of the same type at the same address. */
|
||||
layout_nonempty_base_or_field (rli, decl, binfo, offsets);
|
||||
/* Add the new FIELD_DECL to the list of fields for T. */
|
||||
TREE_CHAIN (decl) = *next_field;
|
||||
*next_field = decl;
|
||||
next_field = &TREE_CHAIN (decl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4423,7 +4426,9 @@ end_of_base (tree binfo)
|
||||
{
|
||||
tree size;
|
||||
|
||||
if (is_empty_class (BINFO_TYPE (binfo)))
|
||||
if (!CLASSTYPE_AS_BASE (BINFO_TYPE (binfo)))
|
||||
size = TYPE_SIZE_UNIT (char_type_node);
|
||||
else if (is_empty_class (BINFO_TYPE (binfo)))
|
||||
/* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
|
||||
allocate some space for it. It cannot have virtual bases, so
|
||||
TYPE_SIZE_UNIT is fine. */
|
||||
|
@ -4435,7 +4435,7 @@ extern int comp_template_parms (const_tree, const_tree);
|
||||
extern bool uses_parameter_packs (tree);
|
||||
extern bool template_parameter_pack_p (const_tree);
|
||||
extern tree make_pack_expansion (tree);
|
||||
extern bool check_for_bare_parameter_packs (tree);
|
||||
extern bool check_for_bare_parameter_packs (tree*);
|
||||
extern tree get_template_info (tree);
|
||||
extern int template_class_depth (tree);
|
||||
extern int is_specialization_of (tree, tree);
|
||||
|
@ -15248,7 +15248,7 @@ cp_parser_base_clause (cp_parser* parser)
|
||||
/* Make this a pack expansion type. */
|
||||
TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
|
||||
else
|
||||
check_for_bare_parameter_packs (TREE_VALUE (base));
|
||||
check_for_bare_parameter_packs (&TREE_VALUE (base));
|
||||
|
||||
TREE_CHAIN (base) = bases;
|
||||
bases = base;
|
||||
|
175
gcc/cp/pt.c
175
gcc/cp/pt.c
@ -2419,11 +2419,19 @@ make_ith_pack_parameter_name (tree name, int i)
|
||||
return get_identifier (newname);
|
||||
}
|
||||
|
||||
/* Structure used to track the progress of find_parameter_pack_r. */
|
||||
/* Structure used to track the progress of find_parameter_packs_r. */
|
||||
struct find_parameter_pack_data
|
||||
{
|
||||
/* TREE_LIST that will contain all of the parameter packs found by
|
||||
the traversal. */
|
||||
tree* parameter_packs;
|
||||
|
||||
/* Set of AST nodes that have been visited by the traversal. */
|
||||
struct pointer_set_t *visited;
|
||||
|
||||
/* Whether we should replace parameter packs with
|
||||
ERROR_MARK_NODE. Used by check_for_bare_parameter_packs. */
|
||||
bool set_packs_to_error;
|
||||
};
|
||||
|
||||
/* Identifies all of the argument packs that occur in a template
|
||||
@ -2436,49 +2444,89 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
tree t = *tp;
|
||||
struct find_parameter_pack_data* ppd =
|
||||
(struct find_parameter_pack_data*)data;
|
||||
bool parameter_pack_p = false;
|
||||
|
||||
/* Don't visit nodes twice, except when we're clearing out parameter
|
||||
packs. */
|
||||
if (pointer_set_contains (ppd->visited, *tp))
|
||||
{
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Identify whether this is a parameter pack or not. */
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
if (TEMPLATE_PARM_PARAMETER_PACK (t))
|
||||
parameter_pack_p = true;
|
||||
break;
|
||||
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
case TEMPLATE_TEMPLATE_PARM:
|
||||
if (TEMPLATE_TYPE_PARAMETER_PACK (t))
|
||||
parameter_pack_p = true;
|
||||
break;
|
||||
|
||||
case PARM_DECL:
|
||||
if (FUNCTION_PARAMETER_PACK_P (t))
|
||||
{
|
||||
/* We don't want to walk into the type of a PARM_DECL,
|
||||
because we don't want to see the type parameter pack. */
|
||||
*walk_subtrees = 0;
|
||||
parameter_pack_p = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not a parameter pack. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (parameter_pack_p)
|
||||
{
|
||||
/* Add this parameter pack to the list. */
|
||||
*ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
|
||||
|
||||
if (ppd->set_packs_to_error)
|
||||
/* The caller requested that we set the parameter packs to
|
||||
ERROR_MARK_NODE so that they will not trip up the compiler
|
||||
later. The caller is responsible for emitting an error. */
|
||||
*tp = error_mark_node;
|
||||
else
|
||||
/* Make sure we do not visit this node again. */
|
||||
pointer_set_insert (ppd->visited, *tp);
|
||||
}
|
||||
else
|
||||
/* Make sure we do not visit this node again. */
|
||||
pointer_set_insert (ppd->visited, *tp);
|
||||
|
||||
if (TYPE_P (t))
|
||||
{
|
||||
tree context = TYPE_CONTEXT (t);
|
||||
cp_walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited);
|
||||
}
|
||||
cp_walk_tree (&TYPE_CONTEXT (t),
|
||||
&find_parameter_packs_r, ppd, NULL);
|
||||
|
||||
/* This switch statement will return immediately if we don't find a
|
||||
parameter pack. */
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
if (TEMPLATE_PARM_PARAMETER_PACK (t))
|
||||
break;
|
||||
return NULL_TREE;
|
||||
|
||||
case BOUND_TEMPLATE_TEMPLATE_PARM:
|
||||
/* Check the template itself. */
|
||||
cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
|
||||
&find_parameter_packs_r, ppd, NULL);
|
||||
/* Check the template arguments. */
|
||||
cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
|
||||
ppd->visited);
|
||||
|
||||
/* Dig out the underlying TEMPLATE_TEMPLATE_PARM. */
|
||||
t = TYPE_TI_TEMPLATE (t);
|
||||
if (DECL_P (t) && TREE_TYPE (t))
|
||||
t = TREE_TYPE (t);
|
||||
NULL);
|
||||
*walk_subtrees = 0;
|
||||
|
||||
/* Fall through. */
|
||||
return NULL_TREE;
|
||||
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
case TEMPLATE_TEMPLATE_PARM:
|
||||
if (TEMPLATE_TYPE_PARAMETER_PACK (t))
|
||||
break;
|
||||
return NULL_TREE;
|
||||
|
||||
case PARM_DECL:
|
||||
if (FUNCTION_PARAMETER_PACK_P (t))
|
||||
{
|
||||
/* We don't want to walk into the type of a PARM_DECL,
|
||||
because we don't want to see the type parameter pack.*/
|
||||
*walk_subtrees = 0;
|
||||
break;
|
||||
}
|
||||
return NULL_TREE;
|
||||
|
||||
case RECORD_TYPE:
|
||||
@ -2489,25 +2537,20 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
case UNION_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
if (TYPE_TEMPLATE_INFO (t))
|
||||
{
|
||||
tree args = TREE_VALUE (TYPE_TEMPLATE_INFO (t));
|
||||
cp_walk_tree (&args, &find_parameter_packs_r, ppd, ppd->visited);
|
||||
}
|
||||
cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
|
||||
&find_parameter_packs_r, ppd, NULL);
|
||||
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
case TEMPLATE_DECL:
|
||||
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
|
||||
&& TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
|
||||
break;
|
||||
|
||||
*walk_subtrees = 0;
|
||||
cp_walk_tree (&TREE_TYPE (t),
|
||||
&find_parameter_packs_r, ppd, NULL);
|
||||
return NULL_TREE;
|
||||
|
||||
case TYPENAME_TYPE:
|
||||
cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
|
||||
ppd, ppd->visited);
|
||||
ppd, NULL);
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
@ -2519,16 +2562,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
|
||||
|
||||
case INTEGER_TYPE:
|
||||
cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
|
||||
ppd, ppd->visited);
|
||||
ppd, NULL);
|
||||
*walk_subtrees = 0;
|
||||
return NULL_TREE;
|
||||
|
||||
default:
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Add this parameter pack to the list. */
|
||||
*ppd->parameter_packs = tree_cons (NULL_TREE, t, *ppd->parameter_packs);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
@ -2541,7 +2581,8 @@ uses_parameter_packs (tree t)
|
||||
struct find_parameter_pack_data ppd;
|
||||
ppd.parameter_packs = ¶meter_packs;
|
||||
ppd.visited = pointer_set_create ();
|
||||
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
|
||||
ppd.set_packs_to_error = false;
|
||||
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, NULL);
|
||||
pointer_set_destroy (ppd.visited);
|
||||
return parameter_packs != NULL_TREE;
|
||||
}
|
||||
@ -2559,6 +2600,8 @@ make_pack_expansion (tree arg)
|
||||
bool for_types = false;
|
||||
struct find_parameter_pack_data ppd;
|
||||
|
||||
ppd.set_packs_to_error = false;
|
||||
|
||||
if (!arg || arg == error_mark_node)
|
||||
return arg;
|
||||
|
||||
@ -2592,7 +2635,7 @@ make_pack_expansion (tree arg)
|
||||
ppd.visited = pointer_set_create ();
|
||||
ppd.parameter_packs = ¶meter_packs;
|
||||
cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
|
||||
&ppd, ppd.visited);
|
||||
&ppd, NULL);
|
||||
|
||||
if (parameter_packs == NULL_TREE)
|
||||
{
|
||||
@ -2610,7 +2653,7 @@ make_pack_expansion (tree arg)
|
||||
/* Determine which parameter packs will be expanded in this
|
||||
argument. */
|
||||
cp_walk_tree (&TREE_VALUE (value), &find_parameter_packs_r,
|
||||
&ppd, ppd.visited);
|
||||
&ppd, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2648,7 +2691,7 @@ make_pack_expansion (tree arg)
|
||||
/* Determine which parameter packs will be expanded. */
|
||||
ppd.parameter_packs = ¶meter_packs;
|
||||
ppd.visited = pointer_set_create ();
|
||||
cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, ppd.visited);
|
||||
cp_walk_tree (&arg, &find_parameter_packs_r, &ppd, NULL);
|
||||
pointer_set_destroy (ppd.visited);
|
||||
|
||||
/* Make sure we found some parameter packs. */
|
||||
@ -2680,20 +2723,21 @@ make_pack_expansion (tree arg)
|
||||
Returns TRUE if there were no bare parameter packs, returns FALSE
|
||||
(and emits an error) if there were bare parameter packs.*/
|
||||
bool
|
||||
check_for_bare_parameter_packs (tree t)
|
||||
check_for_bare_parameter_packs (tree* t)
|
||||
{
|
||||
tree parameter_packs = NULL_TREE;
|
||||
struct find_parameter_pack_data ppd;
|
||||
|
||||
if (!processing_template_decl || !t || t == error_mark_node)
|
||||
if (!processing_template_decl || !t || !*t || *t == error_mark_node)
|
||||
return true;
|
||||
|
||||
if (TREE_CODE (t) == TYPE_DECL)
|
||||
t = TREE_TYPE (t);
|
||||
if (TREE_CODE (*t) == TYPE_DECL)
|
||||
t = &TREE_TYPE (*t);
|
||||
|
||||
ppd.parameter_packs = ¶meter_packs;
|
||||
ppd.visited = pointer_set_create ();
|
||||
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
|
||||
ppd.set_packs_to_error = false;
|
||||
cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
|
||||
pointer_set_destroy (ppd.visited);
|
||||
|
||||
if (parameter_packs)
|
||||
@ -2711,11 +2755,23 @@ check_for_bare_parameter_packs (tree t)
|
||||
name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
|
||||
else
|
||||
name = DECL_NAME (pack);
|
||||
inform (" %qD", name);
|
||||
|
||||
if (name)
|
||||
inform (" %qD", name);
|
||||
else
|
||||
inform (" <anonymous>");
|
||||
|
||||
parameter_packs = TREE_CHAIN (parameter_packs);
|
||||
}
|
||||
|
||||
/* Clean up any references to these parameter packs within the
|
||||
tree. */
|
||||
ppd.parameter_packs = ¶meter_packs;
|
||||
ppd.visited = pointer_set_create ();
|
||||
ppd.set_packs_to_error = true;
|
||||
cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL);
|
||||
pointer_set_destroy (ppd.visited);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2978,7 +3034,7 @@ process_template_parm (tree list, tree parm, bool is_non_type,
|
||||
{
|
||||
/* This template parameter is not a parameter pack, but it
|
||||
should be. Complain about "bare" parameter packs. */
|
||||
check_for_bare_parameter_packs (TREE_TYPE (parm));
|
||||
check_for_bare_parameter_packs (&TREE_TYPE (parm));
|
||||
|
||||
/* Recover by calling this a parameter pack. */
|
||||
is_parameter_pack = true;
|
||||
@ -3382,7 +3438,10 @@ process_partial_specialization (tree decl)
|
||||
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
|
||||
error ("parameter pack argument %qE must be at the end of the template argument list", arg);
|
||||
else
|
||||
error ("parameter pack argument %qT must be at the end of the template argument list", arg);
|
||||
error ("parameter pack argument %qT must be at the end of the template argument list", arg);
|
||||
|
||||
if (packed_args)
|
||||
TREE_VEC_ELT (packed_args, j) = error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3789,7 +3848,7 @@ push_template_decl_real (tree decl, bool is_friend)
|
||||
while (arg && argtype)
|
||||
{
|
||||
if (!FUNCTION_PARAMETER_PACK_P (arg)
|
||||
&& !check_for_bare_parameter_packs (TREE_TYPE (arg)))
|
||||
&& !check_for_bare_parameter_packs (&TREE_TYPE (arg)))
|
||||
{
|
||||
/* This is a PARM_DECL that contains unexpanded parameter
|
||||
packs. We have already complained about this in the
|
||||
@ -3805,11 +3864,11 @@ push_template_decl_real (tree decl, bool is_friend)
|
||||
|
||||
/* Check for bare parameter packs in the return type and the
|
||||
exception specifiers. */
|
||||
check_for_bare_parameter_packs (TREE_TYPE (type));
|
||||
check_for_bare_parameter_packs (TYPE_RAISES_EXCEPTIONS (type));
|
||||
check_for_bare_parameter_packs (&TREE_TYPE (type));
|
||||
check_for_bare_parameter_packs (&TYPE_RAISES_EXCEPTIONS (type));
|
||||
}
|
||||
else
|
||||
check_for_bare_parameter_packs (TREE_TYPE (decl));
|
||||
check_for_bare_parameter_packs (&TREE_TYPE (decl));
|
||||
|
||||
if (is_partial)
|
||||
return process_partial_specialization (decl);
|
||||
@ -3833,6 +3892,8 @@ push_template_decl_real (tree decl, bool is_friend)
|
||||
else
|
||||
error ("parameter pack %qT must be at the end of the"
|
||||
" template parameter list", TREE_TYPE (parm));
|
||||
|
||||
TREE_VALUE (TREE_VEC_ELT (inner_parms, i)) = error_mark_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4755,7 +4816,7 @@ convert_template_argument (tree parm,
|
||||
if (is_type)
|
||||
error (" expected a constant of type %qT, got %qT",
|
||||
TREE_TYPE (parm),
|
||||
(is_tmpl_type ? DECL_NAME (arg) : orig_arg));
|
||||
(DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
|
||||
else if (requires_tmpl_type)
|
||||
error (" expected a class template, got %qE", orig_arg);
|
||||
else
|
||||
@ -13101,6 +13162,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||
nodes. */
|
||||
return 0;
|
||||
|
||||
case ERROR_MARK:
|
||||
/* Unification fails if we hit an error node. */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
gcc_assert (EXPR_P (parm));
|
||||
|
||||
|
@ -508,7 +508,7 @@ finish_cond (tree *cond_p, tree expr)
|
||||
if (TREE_CODE (cond) == DECL_EXPR)
|
||||
expr = cond;
|
||||
|
||||
check_for_bare_parameter_packs (expr);
|
||||
check_for_bare_parameter_packs (&expr);
|
||||
}
|
||||
*cond_p = expr;
|
||||
}
|
||||
@ -618,7 +618,7 @@ finish_expr_stmt (tree expr)
|
||||
else if (!type_dependent_expression_p (expr))
|
||||
convert_to_void (build_non_dependent_expr (expr), "statement");
|
||||
|
||||
check_for_bare_parameter_packs (expr);
|
||||
check_for_bare_parameter_packs (&expr);
|
||||
|
||||
/* Simplification of inner statement expressions, compound exprs,
|
||||
etc can result in us already having an EXPR_STMT. */
|
||||
@ -875,7 +875,7 @@ finish_for_expr (tree expr, tree for_stmt)
|
||||
else if (!type_dependent_expression_p (expr))
|
||||
convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
|
||||
expr = maybe_cleanup_point_expr_void (expr);
|
||||
check_for_bare_parameter_packs (expr);
|
||||
check_for_bare_parameter_packs (&expr);
|
||||
FOR_EXPR (for_stmt) = expr;
|
||||
}
|
||||
|
||||
@ -971,12 +971,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
|
||||
cond = index;
|
||||
}
|
||||
}
|
||||
check_for_bare_parameter_packs (&cond);
|
||||
finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
|
||||
SWITCH_STMT_TYPE (switch_stmt) = orig_type;
|
||||
add_stmt (switch_stmt);
|
||||
push_switch (switch_stmt);
|
||||
SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
|
||||
check_for_bare_parameter_packs (cond);
|
||||
}
|
||||
|
||||
/* Finish the body of a switch-statement, which may be given by
|
||||
@ -1389,7 +1389,7 @@ finish_mem_initializers (tree mem_inits)
|
||||
bound as part of the TREE_PURPOSE. See
|
||||
make_pack_expansion for more information. */
|
||||
if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
|
||||
check_for_bare_parameter_packs (TREE_VALUE (mem));
|
||||
check_for_bare_parameter_packs (&TREE_VALUE (mem));
|
||||
}
|
||||
|
||||
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
|
||||
@ -2306,9 +2306,8 @@ finish_member_declaration (tree decl)
|
||||
DECL_CONTEXT (decl) = current_class_type;
|
||||
|
||||
/* Check for bare parameter packs in the member variable declaration. */
|
||||
if (TREE_CODE (decl) == FIELD_DECL
|
||||
&& !check_for_bare_parameter_packs (TREE_TYPE (decl)))
|
||||
TREE_TYPE (decl) = error_mark_node;
|
||||
if (TREE_CODE (decl) == FIELD_DECL)
|
||||
check_for_bare_parameter_packs (&TREE_TYPE (decl));
|
||||
|
||||
/* [dcl.link]
|
||||
|
||||
|
@ -846,6 +846,9 @@ cp_build_qualified_type_real (tree type,
|
||||
tree
|
||||
canonical_type_variant (tree t)
|
||||
{
|
||||
if (t == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
|
||||
}
|
||||
|
||||
|
@ -6613,7 +6613,7 @@ check_return_expr (tree retval, bool *no_warning)
|
||||
if (processing_template_decl)
|
||||
{
|
||||
current_function_returns_value = 1;
|
||||
check_for_bare_parameter_packs (retval);
|
||||
check_for_bare_parameter_packs (&retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,21 @@
|
||||
2007-11-06 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* testsuite/g++.dg/parser/crash36.C: Tweak expected errors.
|
||||
* testsuite/g++.dg/cpp0x/pr31439.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32114.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32115.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32125.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32126.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32127.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32128.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32253.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr32566.C: New.
|
||||
* testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors.
|
||||
* testsuite/g++.dg/cpp0x/pr31438.C: Ditto.
|
||||
* testsuite/g++.dg/cpp0x/variadic81.C: Ditto.
|
||||
* testsuite/g++.dg/cpp0x/pr31432.C: Ditto.
|
||||
* testsuite/g++.dg/cpp0x/pr31442.C: Ditto.
|
||||
|
||||
2007-11-06 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/33168
|
||||
|
@ -4,5 +4,5 @@ template<typename..., typename> struct A // { dg-error "parameter pack" }
|
||||
static int i;
|
||||
};
|
||||
|
||||
A<int, int> a; // { dg-error "invalid type" }
|
||||
A<char,int> b; // { dg-error "invalid type" }
|
||||
A<int, int> a; // { dg-error "mismatch|expected|invalid type" }
|
||||
A<char,int> b; // { dg-error "mismatch|expected|invalid type" }
|
||||
|
@ -1,9 +1,9 @@
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
template<typename> struct A; // { dg-error "candidates" }
|
||||
template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" }
|
||||
{ // { dg-error "parameter packs|U" }
|
||||
template<typename X> A(X); // { dg-error "parameter packs|U" }
|
||||
template<typename> struct A;
|
||||
template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U|not used|U" }
|
||||
{
|
||||
template<typename X> A(X);
|
||||
};
|
||||
|
||||
A<void(int)> a(0); // { dg-error "no matching" }
|
||||
A<void(int)> a(0); // { dg-error "incomplete type" }
|
||||
|
8
gcc/testsuite/g++.dg/cpp0x/pr31439.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/pr31439.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename...> struct A;
|
||||
|
||||
template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous" }
|
||||
|
||||
template<typename T, typename... U> struct A<T, U...> : A<U...> {};
|
||||
|
||||
A<int> a;
|
@ -1,9 +1,9 @@
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end" }
|
||||
template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end|parameter packs|anonymous" }
|
||||
|
||||
struct B
|
||||
{
|
||||
template <template <typename...> class C> B(C<int>);
|
||||
};
|
||||
|
||||
B b = A<int>();
|
||||
B b = A<int>(); // { dg-error "mismatch|expected" }
|
||||
|
@ -1,8 +1,8 @@
|
||||
// { dg-options "-std=gnu++0x" }
|
||||
template <typename... T> struct A
|
||||
{
|
||||
void foo(T...); // { dg-error "candidates" }
|
||||
A(T... t) { foo(t); } // { dg-error "parameter packs|t|no matching" }
|
||||
void foo(T...);
|
||||
A(T... t) { foo(t); } // { dg-error "parameter packs|t" }
|
||||
};
|
||||
|
||||
A<int> a(0);
|
||||
|
7
gcc/testsuite/g++.dg/cpp0x/pr32114.C
Normal file
7
gcc/testsuite/g++.dg/cpp0x/pr32114.C
Normal file
@ -0,0 +1,7 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename ...T> struct A
|
||||
{
|
||||
typedef typename T::X Y; // { dg-error "not expanded|T" }
|
||||
};
|
||||
|
||||
A<int> a;
|
4
gcc/testsuite/g++.dg/cpp0x/pr32115.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/pr32115.C
Normal file
@ -0,0 +1,4 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename ...T, int = 0> struct A {}; // { dg-error "end of" }
|
||||
|
||||
A<int> a; // { dg-error "mismatch|expected|invalid" }
|
8
gcc/testsuite/g++.dg/cpp0x/pr32125.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/pr32125.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename...> struct A;
|
||||
|
||||
template<typename...T> struct A<T*> // { dg-error "not expanded|T|not used|T" }
|
||||
{
|
||||
A();
|
||||
A(T); // { dg-error "not expanded|T" }
|
||||
};
|
10
gcc/testsuite/g++.dg/cpp0x/pr32126.C
Normal file
10
gcc/testsuite/g++.dg/cpp0x/pr32126.C
Normal file
@ -0,0 +1,10 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename...> struct A;
|
||||
|
||||
template<typename...T> struct A<T> // { dg-error "not expanded|T|not used|T" }
|
||||
{
|
||||
static int i;
|
||||
};
|
||||
|
||||
A<char> a; // { dg-error "incomplete" }
|
||||
A<int> b; // { dg-error "incomplete" }
|
7
gcc/testsuite/g++.dg/cpp0x/pr32127.C
Normal file
7
gcc/testsuite/g++.dg/cpp0x/pr32127.C
Normal file
@ -0,0 +1,7 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename...T> struct A
|
||||
{
|
||||
static T i; // { dg-error "parameter packs|T" }
|
||||
};
|
||||
|
||||
int j = A<int>::i; // { dg-error "not a member" }
|
7
gcc/testsuite/g++.dg/cpp0x/pr32128.C
Normal file
7
gcc/testsuite/g++.dg/cpp0x/pr32128.C
Normal file
@ -0,0 +1,7 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<typename...> struct A;
|
||||
|
||||
template<typename...T, typename...U>
|
||||
struct A<T..., U...> {}; // { dg-error "must be at the end" }
|
||||
|
||||
A<int> a; // { dg-error "incomplete" }
|
9
gcc/testsuite/g++.dg/cpp0x/pr32253.C
Normal file
9
gcc/testsuite/g++.dg/cpp0x/pr32253.C
Normal file
@ -0,0 +1,9 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<void (*... fp)()> struct A
|
||||
{
|
||||
A() { fp(); } // { dg-error "not expanded|fp" }
|
||||
};
|
||||
|
||||
void foo();
|
||||
|
||||
A<foo> a;
|
4
gcc/testsuite/g++.dg/cpp0x/pr32566.C
Normal file
4
gcc/testsuite/g++.dg/cpp0x/pr32566.C
Normal file
@ -0,0 +1,4 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
template<int...> struct A;
|
||||
|
||||
template<template<int> class... T> struct A<T...> {}; // { dg-error "mismatch|expected" }
|
@ -3,9 +3,9 @@
|
||||
|
||||
template<typename> struct A;
|
||||
|
||||
template<typename... T> struct A<T*> // { dg-error "not expanded|note" }
|
||||
{ // { dg-error "not expanded|note" }
|
||||
template<typename... T> struct A<T*> // { dg-error "not expanded|T|not used|T" }
|
||||
{
|
||||
struct B;
|
||||
};
|
||||
|
||||
A<void*> a;
|
||||
A<void*> a; // { dg-error "incomplete" }
|
||||
|
@ -5,7 +5,7 @@
|
||||
template <typename... T> struct A // { dg-error "does not include variadic templates" }
|
||||
{
|
||||
static T &t; // { dg-error "not expanded with|T" }
|
||||
static const int i = sizeof (++t); // { dg-error "invalid use of template type parameter" }
|
||||
static const int i = sizeof (++t);
|
||||
};
|
||||
|
||||
int x[A <int>::i]; // { dg-error "is not an integral constant-expression" }
|
||||
|
Loading…
Reference in New Issue
Block a user