This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix a bunch of variadic template ice-on-invalid PRs


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]