diff mbox

C++ PATCH to fix a part of c++/70513 (ICE-on-invalid with enums)

Message ID 20160421113541.GS28445@redhat.com
State New
Headers show

Commit Message

Marek Polacek April 21, 2016, 11:35 a.m. UTC
On Wed, Apr 20, 2016 at 11:33:55AM -0400, Jason Merrill wrote:
> On 04/08/2016 07:51 AM, Marek Polacek wrote:
> >By the template part of this PR I mean that we ICE on
> >
> >template <typename T>
> >class D
> >{
> >   enum D::A { foo } c;
> >};
> >
> >where clang++ says
> >error: template specialization or definition requires a template parameter list
> >        corresponding to the nested type 'D<T>'
> >which I guess means that a valid code would have "<T>" after "D".
> 
> No, this is misleading; adding the template args wouldn't make the extra
> qualification valid.  We should just give the extra qualification error in
> this case, too.

Oh, I see.  In that case...

> It might help to move your added check to before we push_scope.

This wouldn't help: nested_name_specifier and prev_scope are both "struct D",
but prev_scope contains TYPE_FIELDS, so comparison with == wouldn't work.  But
I wonder if we can't simply use same_type_p then, as in the below.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2016-04-20  Marek Polacek  <polacek@redhat.com>

	PR c/70513
	* parser.c (cp_parser_enum_specifier): Check and possibly error for
	extra qualification.

	* g++.dg/cpp0x/forw_enum12.C: New test.
	* g++.dg/cpp0x/forw_enum13.C: New test.


	Marek

Comments

Jason Merrill April 21, 2016, 1:57 p.m. UTC | #1
On 04/21/2016 07:35 AM, Marek Polacek wrote:
> +	      permerror (type_start_token->location,
> +			 "extra qualification not allowed");
> +	      type = error_mark_node;

If we're using permerror, we shouldn't set type to error_mark_node; if 
we do that, -fpermissive won't make it work.

Jason
diff mbox

Patch

diff --git gcc/cp/parser.c gcc/cp/parser.c
index 0a1ed1a..e9d1995 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -17233,6 +17233,17 @@  cp_parser_enum_specifier (cp_parser* parser)
 			  type, prev_scope, nested_name_specifier);
 	      type = error_mark_node;
 	    }
+	  /* If that scope is the scope where the declaration is being placed
+	     the program is invalid.  */
+	  else if (CLASS_TYPE_P (nested_name_specifier)
+		   && CLASS_TYPE_P (prev_scope)
+		   && same_type_p (nested_name_specifier, prev_scope))
+	    {
+	      permerror (type_start_token->location,
+			 "extra qualification not allowed");
+	      type = error_mark_node;
+	      nested_name_specifier = NULL_TREE;
+	    }
 	}
 
       if (scoped_enum_p)
diff --git gcc/testsuite/g++.dg/cpp0x/forw_enum12.C gcc/testsuite/g++.dg/cpp0x/forw_enum12.C
index e69de29..906ba68 100644
--- gcc/testsuite/g++.dg/cpp0x/forw_enum12.C
+++ gcc/testsuite/g++.dg/cpp0x/forw_enum12.C
@@ -0,0 +1,29 @@ 
+// PR c++/70513
+// { dg-do compile { target c++11 } }
+
+struct S1
+{
+  enum E : int;
+  enum S1::E : int { X } e; // { dg-error "extra qualification not allowed" }
+};
+
+struct S2
+{
+  enum class E : int;
+  enum class S2::E : int { X } e; // { dg-error "extra qualification not allowed" }
+};
+
+struct S3
+{
+  enum struct E : int;
+  enum struct S3::E : int { X } e; // { dg-error "extra qualification not allowed" }
+};
+
+struct S4
+{
+  struct S5
+  {
+    enum E : char;
+    enum S4::S5::E : char { X } e; // { dg-error "extra qualification not allowed" }
+  };
+};
diff --git gcc/testsuite/g++.dg/cpp0x/forw_enum13.C gcc/testsuite/g++.dg/cpp0x/forw_enum13.C
index e69de29..b8027f0 100644
--- gcc/testsuite/g++.dg/cpp0x/forw_enum13.C
+++ gcc/testsuite/g++.dg/cpp0x/forw_enum13.C
@@ -0,0 +1,47 @@ 
+// PR c++/70513
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+class D1
+{
+  enum A : int;
+  enum D1::A : int { foo } c; // { dg-error "extra qualification not allowed" }
+};
+
+template <typename T>
+class D2
+{
+  enum A : int;
+  enum D2<T>::A : int { foo } c; // { dg-error "extra qualification not allowed" }
+};
+
+template <typename T>
+class D3
+{
+  enum D3::A { foo } c; // { dg-error "extra qualification not allowed" }
+};
+
+template <typename T>
+class D4
+{
+  enum D4<T>::A { foo } c; // { dg-error "extra qualification not allowed" }
+};
+
+template <typename T>
+class D5
+{
+  class D6
+  {
+    enum D6::A { foo } c; // { dg-error "extra qualification not allowed" }
+  };
+};
+
+template <typename T>
+class D7
+{
+  class D8
+  {
+    enum A : int;
+    enum D8::A : int { foo } c; // { dg-error "extra qualification not allowed" }
+  };
+};