diff mbox series

[C++] decls with error_node type

Message ID aa78a93a-88f7-dbe7-e34e-184e8ca9e435@acm.org
State New
Headers show
Series [C++] decls with error_node type | expand

Commit Message

Nathan Sidwell May 31, 2019, 5:39 p.m. UTC
I discovered we could occasionally create TYPE_DECLs with 
error_mark_node type, and then successfully push them into the symbol table!

I don't think we should be doing this -- it means TREE_TYPE of a 
TYPE_DECL might not be a type, with resulting ICE fallout.  (When we 
cons up a VAR_DECL to cope with an undefined lookup we give it int type, 
to avoid this kind of thing.)

This patch stops grokdeclarator doing this, by immediately returning 
error_mark_node.  And added an assert to push_template_decl_real, where 
I noticed the problem occurring.

The fallout is some error cascade on symbol lookups that now fail. 
error33.C was particularly screwy:

   typedef void (A::T) ();

would pushing a T into the current scope.

Jason, ok?

nathan

Comments

Jason Merrill June 3, 2019, 5:30 p.m. UTC | #1
On 5/31/19 1:39 PM, Nathan Sidwell wrote:
> I discovered we could occasionally create TYPE_DECLs with 
> error_mark_node type, and then successfully push them into the symbol 
> table!
> 
> I don't think we should be doing this -- it means TREE_TYPE of a 
> TYPE_DECL might not be a type, with resulting ICE fallout.  (When we 
> cons up a VAR_DECL to cope with an undefined lookup we give it int type, 
> to avoid this kind of thing.)
> 
> This patch stops grokdeclarator doing this, by immediately returning 
> error_mark_node.  And added an assert to push_template_decl_real, where 
> I noticed the problem occurring.

> The fallout is some error cascade on symbol lookups that now fail. 

Right, that's why we had the previous behavior, to avoid this extra 
noise.  And then various places check error_operand_p to avoid trying to 
do anything with such a declaration.

Perhaps lookup should return error_mark_node rather than a _DECL with 
error_mark_node type?

Jason
Nathan Sidwell June 5, 2019, 10:34 a.m. UTC | #2
On 6/3/19 1:30 PM, Jason Merrill wrote:
> On 5/31/19 1:39 PM, Nathan Sidwell wrote:

>> The fallout is some error cascade on symbol lookups that now fail. 
> 
> Right, that's why we had the previous behavior, to avoid this extra 
> noise.  And then various places check error_operand_p to avoid trying to 
> do anything with such a declaration.
> 
> Perhaps lookup should return error_mark_node rather than a _DECL with 
> error_mark_node type?

Good idea, but still fails in simlar ways.   I think that's because with 
the curren tbehaviour, it can parse suchan erronous typedef name as a 
declspec seq -- and a var-decl as a var (I now see we set their type to 
error_mark_node too).    This is looking like a rat hole :(

nathan
diff mbox series

Patch

2019-05-31  Nathan Sidwell  <nathan@acm.org>

	* decl.c (grokdeclarator): Don't create decls with error_mark_node
	type.
	* pt.c (push_template_decl_real): Assert decl's type not
	error_mark_node.

	* g++.dg/concepts/pr84423-1.C: Add more expected errors.
	* g++.dg/cpp0x/auto39.C: Likewise.
	* g++.dg/parse/error32.C: Likewise.
	* g++.dg/parse/error33.C: Likewise.

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 271811)
+++ gcc/cp/decl.c	(working copy)
@@ -12082,11 +12082,9 @@  grokdeclarator (const cp_declarator *dec
       if (type_uses_auto (type))
 	{
-	  if (alias_p)
-	    error_at (declspecs->locations[ds_type_spec],
-		      "%<auto%> not allowed in alias declaration");
-	  else
-	    error_at (declspecs->locations[ds_type_spec],
-		      "typedef declared %<auto%>");
-	  type = error_mark_node;
+	  error_at (declspecs->locations[ds_type_spec],
+		    alias_p
+		    ? G_("%<auto%> not allowed in alias declaration")
+		    : G_("typedef declared %<auto%>"));
+	  return error_mark_node;
 	}
 
@@ -12097,5 +12095,5 @@  grokdeclarator (const cp_declarator *dec
 	{
 	  error ("typedef name may not be a nested-name-specifier");
-	  type = error_mark_node;
+	  return error_mark_node;
 	}
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 271811)
+++ gcc/cp/pt.c	(working copy)
@@ -5450,4 +5450,6 @@  push_template_decl_real (tree decl, bool
     return error_mark_node;
 
+  gcc_checking_assert (TREE_TYPE (decl) != error_mark_node);
+
   /* See if this is a partial specialization.  */
   is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
Index: gcc/testsuite/g++.dg/concepts/pr84423-1.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/pr84423-1.C	(revision 271811)
+++ gcc/testsuite/g++.dg/concepts/pr84423-1.C	(working copy)
@@ -6,3 +6,3 @@  template<typename> using A = auto;  // {
 template<template<typename> class> struct B {};
 
-B<A> b;
+B<A> b;  // { dg-error "not declared|invalid" }
Index: gcc/testsuite/g++.dg/cpp0x/auto39.C
===================================================================
--- gcc/testsuite/g++.dg/cpp0x/auto39.C	(revision 271811)
+++ gcc/testsuite/g++.dg/cpp0x/auto39.C	(working copy)
@@ -4,3 +4,3 @@ 
 typedef auto T;     // { dg-error "9:typedef declared 'auto'" }
 
-void foo() { T(); }
+void foo() { T(); } // { dg-error "not declared" }
Index: gcc/testsuite/g++.dg/parse/error32.C
===================================================================
--- gcc/testsuite/g++.dg/parse/error32.C	(revision 271811)
+++ gcc/testsuite/g++.dg/parse/error32.C	(working copy)
@@ -8,5 +8,5 @@  typedef void (A::T)(); /* { dg-error "ty
 void foo()
 {
-  T t;
+  T t; /* { dg-error "was not declared" } */
   t; /* { dg-error "was not declared" } */
 }
Index: gcc/testsuite/g++.dg/parse/error33.C
===================================================================
--- gcc/testsuite/g++.dg/parse/error33.C	(revision 271811)
+++ gcc/testsuite/g++.dg/parse/error33.C	(working copy)
@@ -9,8 +9,9 @@  struct A
 typedef void (A::T)(); /* { dg-error "typedef name may not be a nested" } */
 
-void bar(T); /* { dg-message "note: declared here" } */
+void bar(T); /* { dg-error "declared void" } */
+// { dg-error "not declared" "" { target *-*-* } .-1 }
 
 void baz()
 {
-  bar(&A::foo); /* { dg-error "too many arguments" } */
+  bar(&A::foo); /* { dg-error "not declared" } */
 }