diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2007-11-06 14:37:56 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2007-11-06 14:37:56 +0000 |
commit | 1ad8aeeb962a281f654be3bc0a7a2dd4015d317b (patch) | |
tree | 83b93ec8d6832f10e12b455400f3daa46f208750 /gcc | |
parent | 3de36a09ac124ff2b1bf50c822259ca206f88f23 (diff) | |
download | gcc-1ad8aeeb962a281f654be3bc0a7a2dd4015d317b.tar.gz |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 54 | ||||
-rw-r--r-- | gcc/cp/class.c | 37 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 173 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 15 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31432.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31438.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31439.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31442.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr31445.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32114.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32115.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32125.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32126.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32127.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32128.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32253.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr32566.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic81.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/crash36.C | 2 |
24 files changed, 304 insertions, 96 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2f0d55274b6..9fff78d0fbf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4453b346a69..e468db30442 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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; - - /* 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); + 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); + } } 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. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5f43c13d3d8..f954da5d850 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4729d1ed5dd..23994b0808a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 53edd31cd33..0ac7314c72b 100644 --- a/gcc/cp/pt.c +++ b/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; - if (TYPE_P (t)) + /* 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) { - tree context = TYPE_CONTEXT (t); - cp_walk_tree (&context, &find_parameter_packs_r, ppd, ppd->visited); + /* 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)) + 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)); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 3f45f712e0e..50118a25f12 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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] diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 64efda50d65..fba7c2281f0 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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)); } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 862787a10c8..d167de20c06 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1d9a9c6fe9a..6689530ba54 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31432.C b/gcc/testsuite/g++.dg/cpp0x/pr31432.C index cb8826e5957..8016ee69d75 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31432.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31432.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31438.C b/gcc/testsuite/g++.dg/cpp0x/pr31438.C index 3a125634ffb..0e27971494b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31438.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31438.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C new file mode 100644 index 00000000000..420dc082f08 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr31439.C @@ -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; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31442.C b/gcc/testsuite/g++.dg/cpp0x/pr31442.C index 050e2999566..f4e411c4505 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31442.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31442.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31445.C b/gcc/testsuite/g++.dg/cpp0x/pr31445.C index 025cb9606c3..b3f2b5b09da 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31445.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31445.C @@ -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); diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32114.C b/gcc/testsuite/g++.dg/cpp0x/pr32114.C new file mode 100644 index 00000000000..e78dfdf1df9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32114.C @@ -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; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32115.C b/gcc/testsuite/g++.dg/cpp0x/pr32115.C new file mode 100644 index 00000000000..a721eed4eb7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32115.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32125.C b/gcc/testsuite/g++.dg/cpp0x/pr32125.C new file mode 100644 index 00000000000..154cd85487d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32125.C @@ -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" } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32126.C b/gcc/testsuite/g++.dg/cpp0x/pr32126.C new file mode 100644 index 00000000000..e7c61bd0c3c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32126.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32127.C b/gcc/testsuite/g++.dg/cpp0x/pr32127.C new file mode 100644 index 00000000000..8e4bc0050b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32127.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32128.C b/gcc/testsuite/g++.dg/cpp0x/pr32128.C new file mode 100644 index 00000000000..5876dbec485 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32128.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32253.C b/gcc/testsuite/g++.dg/cpp0x/pr32253.C new file mode 100644 index 00000000000..d8f7b03b92f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32253.C @@ -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; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32566.C b/gcc/testsuite/g++.dg/cpp0x/pr32566.C new file mode 100644 index 00000000000..f6e7a5b548d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr32566.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic81.C b/gcc/testsuite/g++.dg/cpp0x/variadic81.C index d710128df49..322f249de9a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic81.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic81.C @@ -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" } diff --git a/gcc/testsuite/g++.dg/parse/crash36.C b/gcc/testsuite/g++.dg/parse/crash36.C index 1e5ab8f2562..e73e928350d 100644 --- a/gcc/testsuite/g++.dg/parse/crash36.C +++ b/gcc/testsuite/g++.dg/parse/crash36.C @@ -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" } |