From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2326 invoked by alias); 13 Nov 2007 14:08:08 -0000 Received: (qmail 2317 invoked by uid 22791); 13 Nov 2007 14:08:06 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 13 Nov 2007 14:08:03 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.1) with ESMTP id lADE60np029239; Tue, 13 Nov 2007 09:06:00 -0500 Received: from devserv.devel.redhat.com (devserv.devel.redhat.com [10.10.36.72]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id lADE60a5026640; Tue, 13 Nov 2007 09:06:00 -0500 Received: from devserv.devel.redhat.com (localhost.localdomain [127.0.0.1]) by devserv.devel.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id lADE605Q019036; Tue, 13 Nov 2007 09:06:00 -0500 Received: (from jakub@localhost) by devserv.devel.redhat.com (8.12.11.20060308/8.12.11/Submit) id lADE60il019034; Tue, 13 Nov 2007 09:06:00 -0500 Date: Tue, 13 Nov 2007 14:59:00 -0000 From: Jakub Jelinek To: Jason Merrill , Mark Mitchell Cc: Doug Gregor , gcc-patches@gcc.gnu.org Subject: [C++ PATCH] Fix a bunch of variadic template ice-on-invalid PRs Message-ID: <20071113140600.GJ5451@devserv.devel.redhat.com> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-11/txt/msg00713.txt.bz2 Hi! This patch fixes a couple of ice-on-invalid bugs. One problem is that the set_packs_to_error replacement of invalid pack uses doesn't play well with shared POINTER_TYPE trees. In this case the first time check_for_bare_parameter_packs sees a pointer to invalid pack use, it will issue error and change the type to pointer to error_mark_node. But the same pointer can appear in other places, where g++ will no longer issue any error (that's arguably a bug), but also that many parts of the FE aren't prepared to handle pointers to error_mark_node in arbitrary places. The patch below (first two hunks) fixes that by setting to error_mark_node the outermost POINTER_TYPE instead, so multiple errors are emitted as they should if errors are in multiple places and more importantly check_for_bare_parameter_packs fails each time there is an error. Another problem is that the FE doesn't expect return type of a function to be an error_mark_node. Normally, when the return type is invalid, it is set to integer_type_node, see: /* Extract the basic type from the decl-specifier-seq. */ type = declspecs->type; if (type == error_mark_node) { type = NULL_TREE; type_was_error_mark_node = true; } and if (type_was_error_mark_node) /* We've already issued an error, don't complain more. */; else if (in_system_header || flag_ms_extensions) /* Allow it, sigh. */; else if (pedantic || ! is_main) pedwarn ("ISO C++ forbids declaration of %qs with no type", name); else warning (OPT_Wreturn_type, "ISO C++ forbids declaration of %qs with no type", name); type = integer_type_node; in decl.c. So this patch does the same if check_for_bare_parameter_packs fails. And the last fix is to return error_mark_node from push_template_decl_real if check_for_bare_parameter_packs fails for types of TYPE_DECLs, VAR_DECLs etc., so that errorneous field etc. isn't added to the template. Regtested on x86_64-linux, ok for trunk? 2007-11-13 Jakub Jelinek PR c++/34054 PR c++/34056 PR c++/34057 PR c++/34058 PR c++/34060 * pt.c (find_parameter_packs_r): If ppd->set_packs_to_error, set to error_mark_node the outermost POINTER_TYPE to the pack if it is seen in a POINTER_TYPE. (push_template_decl_real): If check_for_bare_parameter_packs fails for function return type, set the return type to integer_type_node. If check_for_bare_parameter_packs failed for non-function, return error_mark_node. * g++.dg/parse/crash36.C: Add another dg-error. * g++.dg/cpp0x/pr34054.C: New test. * g++.dg/cpp0x/pr34056.C: New test. * g++.dg/cpp0x/pr34057.C: New test. * g++.dg/cpp0x/pr34058.C: New test. * g++.dg/cpp0x/pr34060.C: New test. --- gcc/cp/pt.c.jj 2007-11-10 01:18:06.000000000 +0100 +++ gcc/cp/pt.c 2007-11-13 14:17:20.000000000 +0100 @@ -2454,6 +2454,7 @@ find_parameter_packs_r (tree *tp, int *w return NULL_TREE; } +recheck: /* Identify whether this is a parameter pack or not. */ switch (TREE_CODE (t)) { @@ -2478,6 +2479,16 @@ find_parameter_packs_r (tree *tp, int *w } break; + case POINTER_TYPE: + if (ppd->set_packs_to_error) + /* Pointer types are shared, set in that case the outermost + POINTER_TYPE to error_mark_node rather than the parameter pack. */ + { + t = TREE_TYPE (t); + goto recheck; + } + break; + default: /* Not a parameter pack. */ break; @@ -2553,7 +2564,6 @@ find_parameter_packs_r (tree *tp, int *w ppd, NULL); *walk_subtrees = 0; return NULL_TREE; - case TYPE_PACK_EXPANSION: case EXPR_PACK_EXPANSION: @@ -3864,11 +3874,15 @@ push_template_decl_real (tree decl, bool /* Check for bare parameter packs in the return type and the exception specifiers. */ - 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 - 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) return process_partial_specialization (decl); --- gcc/testsuite/g++.dg/parse/crash36.C.jj 2007-11-06 22:36:10.000000000 +0100 +++ gcc/testsuite/g++.dg/parse/crash36.C 2007-11-13 14:27:41.000000000 +0100 @@ -5,7 +5,7 @@ template struct A // { dg-error "does not include variadic templates" } { static T &t; // { dg-error "not expanded with|T" } - static const int i = sizeof (++t); + static const int i = sizeof (++t); // { dg-error "was not declared in this scope" } }; int x[A ::i]; // { dg-error "is not an integral constant-expression" } --- gcc/testsuite/g++.dg/cpp0x/pr34054.C.jj 2007-11-13 14:04:31.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr34054.C 2007-11-13 14:06:45.000000000 +0100 @@ -0,0 +1,5 @@ +// PR c++/34054 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template T foo() {} // { dg-error "not expanded|T" } --- gcc/testsuite/g++.dg/cpp0x/pr34056.C.jj 2007-11-13 14:11:24.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr34056.C 2007-11-13 14:06:34.000000000 +0100 @@ -0,0 +1,10 @@ +// PR c++/34056 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template struct A +{ + void foo (T *) { ++p; } // { dg-error "not expanded|T" } + void bar (T **) { } // { dg-error "not expanded|T" } + T *p; // { dg-error "not expanded|T" } +}; --- gcc/testsuite/g++.dg/cpp0x/pr34057.C.jj 2007-11-13 14:32:20.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr34057.C 2007-11-13 14:29:24.000000000 +0100 @@ -0,0 +1,8 @@ +// PR c++/34057 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template struct A +{ + typedef T X __attribute__ ((vector_size (8))); // { dg-error "not expanded|T" } +}; --- gcc/testsuite/g++.dg/cpp0x/pr34058.C.jj 2007-11-13 14:32:20.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr34058.C 2007-11-13 14:29:50.000000000 +0100 @@ -0,0 +1,10 @@ +// PR c++/34058 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template struct A +{ + typedef T X; // { dg-error "not expanded|T" } +}; + +A a; --- gcc/testsuite/g++.dg/cpp0x/pr34060.C.jj 2007-11-13 14:32:20.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr34060.C 2007-11-13 14:31:06.000000000 +0100 @@ -0,0 +1,11 @@ +// PR c++/34060 +// { dg-do compile } +// { dg-options "-std=c++0x" } + +template struct A +{ + template struct B {}; + template struct B {}; // { dg-error "not expanded|T" } +}; + +A<0>::Bb; Jakub