public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PR c++/81247] ICE with bogus input
@ 2017-06-29 18:25 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2017-06-29 18:25 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 769 bytes --]

This fixes 81247.  There are two parts,

firstly it seems pointless to parse try and parse a namespace body when 
there's a missing '{'.  I changed the parser to immediately close the 
new namespace and return in that case.

However, the bug is in my updated do_pushdecl handling.  When the 
incoming decl's CONTEXT is not CURRENT_NAMESPACE, we search the context 
for a matching decl, but push into CURRENT_NAMESPACE if there's no 
match.  But I'd not updated OLD, which holds the current binding for 
UPDATE_BINDING's use.  In this case that meant we silently smashed the 
existing binding to a namespace.

This behaviour of pushing into current namespace does seem odd, but it's 
what the previous code did.  I don't fully understand why.

nathan
-- 
Nathan Sidwell

[-- Attachment #2: pr81247.diff --]
[-- Type: text/x-patch, Size: 3261 bytes --]

2017-06-29  Nathan Sidwell  <nathan@acm.org>

	PR c++/81247
	* parser.c (cp_parser_namespace_definition): Immediately close the
	namespace if there's no open-brace.
	* name-lookup.c (do_pushdecl): Reset OLD when pushing into new
	namespace.

	PR c++/81247
	* g++.dg/parse/pr81247-[abc].C: New.

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 249796)
+++ cp/name-lookup.c	(working copy)
@@ -2422,6 +2422,9 @@ do_pushdecl (tree decl, bool is_friend)
 	{
 	  ns = current_namespace;
 	  slot = find_namespace_slot (ns, name, true);
+	  /* Update OLD to reflect the namespace we're going to be
+	     pushing into.  */
+	  old = MAYBE_STAT_DECL (*slot);
 	}
 
       old = update_binding (level, binding, slot, old, decl, is_friend);
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 249796)
+++ cp/parser.c	(working copy)
@@ -18397,13 +18397,14 @@ cp_parser_namespace_definition (cp_parse
   warning  (OPT_Wnamespaces, "namespace %qD entered", current_namespace);
 
   /* Look for the `{' to validate starting the namespace.  */
-  cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+  if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+    {
+      /* Parse the body of the namespace.  */
+      cp_parser_namespace_body (parser);
 
-  /* Parse the body of the namespace.  */
-  cp_parser_namespace_body (parser);
-
-  /* Look for the final `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+      /* Look for the final `}'.  */
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+    }
 
   if (has_visibility)
     pop_visibility (1);
Index: testsuite/g++.dg/parse/pr81247-a.C
===================================================================
--- testsuite/g++.dg/parse/pr81247-a.C	(revision 0)
+++ testsuite/g++.dg/parse/pr81247-a.C	(working copy)
@@ -0,0 +1,13 @@
+// PR c++/81247 ICE
+
+namespace N  // { dg-message "previous declaration" }
+// { dg-error "expected" "" { target *-*-* } .+1 }
+template < typename T > class A
+{ // { dg-error "redeclared as different" }
+  template < T > friend class N;
+};
+
+void f ()
+{
+  A < int > a1; //  { dg-message "required from here" }
+}
Index: testsuite/g++.dg/parse/pr81247-b.C
===================================================================
--- testsuite/g++.dg/parse/pr81247-b.C	(revision 0)
+++ testsuite/g++.dg/parse/pr81247-b.C	(working copy)
@@ -0,0 +1,14 @@
+// PR c++/81247 confused error
+
+namespace N { // { dg-message "previous declaration" }
+}
+
+template < typename T > class A
+{ // { dg-error "redeclared as different" }
+  template < T > friend class N;
+};
+
+void f ()
+{
+  A < int > a1;
+}
Index: testsuite/g++.dg/parse/pr81247-c.C
===================================================================
--- testsuite/g++.dg/parse/pr81247-c.C	(revision 0)
+++ testsuite/g++.dg/parse/pr81247-c.C	(working copy)
@@ -0,0 +1,13 @@
+// PR c++/81247 confused error
+
+namespace N { // { dg-message "previous declaration" }
+  template < typename T > class A
+  { // { dg-error "conflicts with a previous" }
+    template < T > friend class N;
+  };
+}
+
+void f ()
+{
+  N::A < int > a1;
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-06-29 18:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-29 18:25 [PR c++/81247] ICE with bogus input Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).