This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix a bunch of variadic template ice-on-invalid PRs
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>, Mark Mitchell <mark at codesourcery dot com>
- Cc: Doug Gregor <doug dot gregor at gmail dot com>, gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Nov 2007 09:06:00 -0500
- Subject: [C++ PATCH] Fix a bunch of variadic template ice-on-invalid PRs
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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 <jakub@redhat.com>
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 <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);
+ static const int i = sizeof (++t); // { dg-error "was not declared in this scope" }
};
int x[A <int>::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<typename... T> 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<typename... T> 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 <typename... T> 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 <typename...T> struct A
+{
+ typedef T X; // { dg-error "not expanded|T" }
+};
+
+A<int> 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 <int> struct A
+{
+ template <typename... > struct B {};
+ template <typename... T> struct B <int, T *> {}; // { dg-error "not expanded|T" }
+};
+
+A<0>::B<int>b;
Jakub