From 4439d02f0f5881b186b7d3430a9504310e227e30 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 15 Jan 2008 18:08:00 +0000 Subject: [PATCH] re PR c++/34051 (ICE in dependent_type_p with variadic templates) 2008-01-15 Douglas Gregor PR c++/34051 PR c++/34055 PR c++/34102 PR c++/34103 * typeck.c (check_return_expr): If there are bare parameter packs in the return value, set it to error_mark_node. * tree.c (cp_walk_subtrees): Walk USING_DECL nodes. * pt.c (find_parameter_packs_r): Look at the type of IDENTIFIER_NODEs (e.g., for user-defined conversions). (check_for_bare_parameter_packs): Flip the result: now returns TRUE when there were bare parameter packs, FALSE otherwise. (push_template_decl_real): Deal with flipped result of check_for_bare_parameter_packs. * semantics.c (finish_cond): If there are bare parameter packs in the conditional, set it to error_mark_node. (finish_expr_stmt): If there are bare parameter packs in the expression, set it to error_mark_node. (finish_for_expr): Ditto. (finish_switch_cond): If there are bare parameter packs in the conditional, set it to error_mark_node. (finish_mem_initializers): If there are bare parameter packs in the member initializer, set it to error_mark_node. (finish_member_declaration): Check the attributes of the declaration for bare parameter packs, and remove the attributes if any have bare parameter packs. * parser.c (cp_parser_using_declaration): Check the using declaration for bare parameter packs. (cp_parser_base_clause): If there are bare parameter packs in a base specifier, don't add it to the chain. 2008-01-15 Douglas Gregor PR c++/34051 PR c++/34055 PR c++/34102 PR c++/34103 * g++.dg/cpp0x/vt-34051-2.C: New. * g++.dg/cpp0x/vt-34102.C: New. * g++.dg/cpp0x/vt-34051.C: New. * g++.dg/cpp0x/vt-34055.C: New. * g++.dg/cpp0x/vt-34103.C: New. From-SVN: r131547 --- gcc/cp/ChangeLog | 32 +++++++++++++++++++++++++ gcc/cp/parser.c | 20 +++++++++++----- gcc/cp/pt.c | 21 +++++++++------- gcc/cp/semantics.c | 24 +++++++++++++------ gcc/cp/tree.c | 7 ++++++ gcc/cp/typeck.c | 3 ++- gcc/testsuite/ChangeLog | 19 +++++++++++++++ gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C | 7 ++++++ gcc/testsuite/g++.dg/cpp0x/vt-34051.C | 12 ++++++++++ gcc/testsuite/g++.dg/cpp0x/vt-34055.C | 10 ++++++++ gcc/testsuite/g++.dg/cpp0x/vt-34102.C | 7 ++++++ gcc/testsuite/g++.dg/cpp0x/vt-34103.C | 7 ++++++ 12 files changed, 147 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-34051.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-34055.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-34102.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/vt-34103.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0b6ec64b5efa..5325bcdd24c4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,35 @@ +2008-01-15 Douglas Gregor + + PR c++/34051 + PR c++/34055 + PR c++/34102 + PR c++/34103 + * typeck.c (check_return_expr): If there are bare parameter packs + in the return value, set it to error_mark_node. + * tree.c (cp_walk_subtrees): Walk USING_DECL nodes. + * pt.c (find_parameter_packs_r): Look at the type of + IDENTIFIER_NODEs (e.g., for user-defined conversions). + (check_for_bare_parameter_packs): Flip the result: now returns + TRUE when there were bare parameter packs, FALSE otherwise. + (push_template_decl_real): Deal with flipped result of + check_for_bare_parameter_packs. + * semantics.c (finish_cond): If there are bare parameter packs in + the conditional, set it to error_mark_node. + (finish_expr_stmt): If there are bare parameter packs in the + expression, set it to error_mark_node. + (finish_for_expr): Ditto. + (finish_switch_cond): If there are bare parameter packs in + the conditional, set it to error_mark_node. + (finish_mem_initializers): If there are bare parameter packs in + the member initializer, set it to error_mark_node. + (finish_member_declaration): Check the attributes of the + declaration for bare parameter packs, and remove the attributes if + any have bare parameter packs. + * parser.c (cp_parser_using_declaration): Check the using + declaration for bare parameter packs. + (cp_parser_base_clause): If there are bare parameter packs in a + base specifier, don't add it to the chain. + 2008-01-15 Douglas Gregor PR c++/34314 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 16f5a4e4c065..1400424c2fff 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11748,14 +11748,20 @@ cp_parser_using_declaration (cp_parser* parser, { /* Create the USING_DECL. */ decl = do_class_using_decl (parser->scope, identifier); - /* Add it to the list of members in this class. */ - finish_member_declaration (decl); + + if (check_for_bare_parameter_packs (&decl)) + return false; + else + /* Add it to the list of members in this class. */ + finish_member_declaration (decl); } else { decl = cp_parser_lookup_name_simple (parser, identifier); if (decl == error_mark_node) cp_parser_name_lookup_error (parser, identifier, decl, NULL); + else if (check_for_bare_parameter_packs (&decl)) + return false; else if (!at_namespace_scope_p ()) do_local_using_decl (decl, qscope, identifier); else @@ -15263,11 +15269,13 @@ cp_parser_base_clause (cp_parser* parser) if (pack_expansion_p) /* Make this a pack expansion type. */ TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base)); - else - check_for_bare_parameter_packs (&TREE_VALUE (base)); + - TREE_CHAIN (base) = bases; - bases = base; + if (!check_for_bare_parameter_packs (&TREE_VALUE (base))) + { + TREE_CHAIN (base) = bases; + bases = base; + } } /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d364b20e9c56..57dc8f86766b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2577,6 +2577,11 @@ recheck: *walk_subtrees = 0; return NULL_TREE; + case IDENTIFIER_NODE: + cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd, NULL); + *walk_subtrees = 0; + return NULL_TREE; + default: return NULL_TREE; } @@ -2731,8 +2736,8 @@ make_pack_expansion (tree arg) g(h(args)), or f(g(h(args))), because we would produce erroneous error messages. - Returns TRUE if there were no bare parameter packs, returns FALSE - (and emits an error) if there were bare parameter packs.*/ + Returns TRUE and emits an error if there were bare parameter packs, + returns FALSE otherwise. */ bool check_for_bare_parameter_packs (tree* t) { @@ -2740,7 +2745,7 @@ check_for_bare_parameter_packs (tree* t) struct find_parameter_pack_data ppd; if (!processing_template_decl || !t || !*t || *t == error_mark_node) - return true; + return false; if (TREE_CODE (*t) == TYPE_DECL) t = &TREE_TYPE (*t); @@ -2783,10 +2788,10 @@ check_for_bare_parameter_packs (tree* t) cp_walk_tree (t, &find_parameter_packs_r, &ppd, NULL); pointer_set_destroy (ppd.visited); - return false; + return true; } - return true; + return false; } /* Expand any parameter packs that occur in the template arguments in @@ -3885,7 +3890,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 @@ -3901,14 +3906,14 @@ push_template_decl_real (tree decl, bool is_friend) /* Check for bare parameter packs in the return type and the exception specifiers. */ - if (!check_for_bare_parameter_packs (&TREE_TYPE (type))) + if (check_for_bare_parameter_packs (&TREE_TYPE (type))) /* Errors were already issued, set return type to int as the frontend doesn't expect error_mark_node as the return type. */ TREE_TYPE (type) = integer_type_node; check_for_bare_parameter_packs (&TYPE_RAISES_EXCEPTIONS (type)); } - else if (!check_for_bare_parameter_packs (&TREE_TYPE (decl))) + else if (check_for_bare_parameter_packs (&TREE_TYPE (decl))) return error_mark_node; if (is_partial) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0e8c435dcc8b..8cf9ceba3890 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -508,7 +508,8 @@ finish_cond (tree *cond_p, tree expr) if (TREE_CODE (cond) == DECL_EXPR) expr = cond; - check_for_bare_parameter_packs (&expr); + if (check_for_bare_parameter_packs (&expr)) + *cond_p = error_mark_node; } *cond_p = expr; } @@ -618,7 +619,8 @@ 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); + if (check_for_bare_parameter_packs (&expr)) + expr = error_mark_node; /* Simplification of inner statement expressions, compound exprs, etc can result in us already having an EXPR_STMT. */ @@ -875,7 +877,8 @@ 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); + if (check_for_bare_parameter_packs (&expr)) + expr = error_mark_node; FOR_EXPR (for_stmt) = expr; } @@ -971,7 +974,8 @@ finish_switch_cond (tree cond, tree switch_stmt) cond = index; } } - check_for_bare_parameter_packs (&cond); + if (check_for_bare_parameter_packs (&cond)) + cond = error_mark_node; finish_cond (&SWITCH_STMT_COND (switch_stmt), cond); SWITCH_STMT_TYPE (switch_stmt) = orig_type; add_stmt (switch_stmt); @@ -1388,8 +1392,9 @@ finish_mem_initializers (tree mem_inits) any parameter packs in the TREE_VALUE have already been 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)); + if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION + && check_for_bare_parameter_packs (&TREE_VALUE (mem))) + TREE_VALUE (mem) = error_mark_node; } add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits)); @@ -2325,7 +2330,12 @@ finish_member_declaration (tree decl) /* Check for bare parameter packs in the member variable declaration. */ if (TREE_CODE (decl) == FIELD_DECL) - check_for_bare_parameter_packs (&TREE_TYPE (decl)); + { + if (check_for_bare_parameter_packs (&TREE_TYPE (decl))) + TREE_TYPE (decl) = error_mark_node; + if (check_for_bare_parameter_packs (&DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) = NULL_TREE; + } /* [dcl.link] diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 843f6c45590c..7459266d43ab 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2351,6 +2351,13 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, *walk_subtrees_p = 0; break; + case USING_DECL: + WALK_SUBTREE (DECL_NAME (*tp)); + WALK_SUBTREE (USING_DECL_SCOPE (*tp)); + WALK_SUBTREE (USING_DECL_DECLS (*tp)); + *walk_subtrees_p = 0; + break; + case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (*tp)) WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp)); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0f7ecf723a48..50a844a95e0e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6642,7 +6642,8 @@ check_return_expr (tree retval, bool *no_warning) if (processing_template_decl) { current_function_returns_value = 1; - check_for_bare_parameter_packs (&retval); + if (check_for_bare_parameter_packs (&retval)) + retval = error_mark_node; return retval; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3ae1bd2ff1d4..10cc27d77928 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2008-01-15 Douglas Gregor + + PR c++/34051 + PR c++/34055 + PR c++/34102 + PR c++/34103 + * g++.dg/cpp0x/vt-34051-2.C: New. + * g++.dg/cpp0x/vt-34102.C: New. + * g++.dg/cpp0x/vt-34051.C: New. + * g++.dg/cpp0x/vt-34055.C: New. + * g++.dg/cpp0x/vt-34103.C: New. + +2008-01-15 Douglas Gregor + + PR c++/34314 + * g++.dg/cpp0x/vt-34314.C: New. + * g++.dg/cpp0x/variadic79.C: Fix the error message to reflect + reality (the error message was wrong previously). + 2008-01-15 Douglas Gregor PR c++/33964 diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C new file mode 100644 index 000000000000..2c7bb50f081b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C @@ -0,0 +1,7 @@ +// { dg-options "-std=c++0x" } +template struct A +{ + int i __attribute__((aligned(__alignof(T)))); // { dg-error "parameter packs|T" } +}; + +A a; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C new file mode 100644 index 000000000000..88ae56703233 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C @@ -0,0 +1,12 @@ +// { dg-options "-std=c++0x" } +struct A +{ + operator int(); +}; + +template struct B : A +{ + using A::operator T; // { dg-error "parameter packs|T" } +}; + +B b; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C new file mode 100644 index 000000000000..921b813c82e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C @@ -0,0 +1,10 @@ +// { dg-options "-std=c++0x" } +// PR c++/34055 +template struct A; // { dg-error "declaration" } + +template struct A // { dg-error "parameter packs|T" } +{ + void foo(); +}; + +template void A::foo() {} // { dg-error "invalid use" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34102.C b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C new file mode 100644 index 000000000000..00f0b4f4aace --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C @@ -0,0 +1,7 @@ +// { dg-options "-std=c++0x" } +// PR c++/34102 +struct A {}; + +template struct B : virtual A {}; + +template struct C : B {}; // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34103.C b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C new file mode 100644 index 000000000000..3bbbb46a0120 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C @@ -0,0 +1,7 @@ +// { dg-options "-std=c++0x" } +// PR c++/34103 +template struct A {}; + +template void foo(A, A); // { dg-error "parameter packs|T" } + +template void foo(A, A) {} // { dg-error "parameter packs|T" } -- 2.47.2