From e765a228a54752519e75bf6b799ae4ad4bfa72e9 Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Thu, 6 Jun 2013 22:49:34 -0400
Subject: [PATCH] decl.c (grokdeclarator): Keep a decl with error type.

	* decl.c (grokdeclarator): Keep a decl with error type.
	(grokfield, grokbitfield): Likewise.
	* pt.c (instantiate_class_template_1): Likewise.
	(tsubst_decl): Drop redundant error.
	* class.c (walk_subobject_offsets): Handle erroneous fields.
	* typeck2.c (process_init_constructor_record): Likewise.

From-SVN: r199779
---
 gcc/cp/ChangeLog                             |  9 +++++++++
 gcc/cp/class.c                               |  4 +++-
 gcc/cp/decl.c                                | 16 ++++------------
 gcc/cp/decl2.c                               |  8 ++++++--
 gcc/cp/pt.c                                  |  9 +++------
 gcc/cp/typeck2.c                             |  2 ++
 gcc/testsuite/g++.dg/cpp0x/noexcept15.C      |  4 ++--
 gcc/testsuite/g++.dg/init/array26.C          |  2 +-
 gcc/testsuite/g++.dg/template/error2.C       |  5 ++---
 gcc/testsuite/g++.dg/template/instantiate3.C |  2 +-
 10 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f8bacf5d42ba..c53a9ff0b5a0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2013-06-06  Jason Merrill  <jason@redhat.com>
+
+	* decl.c (grokdeclarator): Keep a decl with error type.
+	(grokfield, grokbitfield): Likewise.
+	* pt.c (instantiate_class_template_1): Likewise.
+	(tsubst_decl): Drop redundant error.
+	* class.c (walk_subobject_offsets): Handle erroneous fields.
+	* typeck2.c (process_init_constructor_record): Likewise.
+
 2013-06-05  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/51908
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 40e6d3eed73d..286164d02029 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3779,7 +3779,9 @@ walk_subobject_offsets (tree type,
 
       /* Iterate through the fields of TYPE.  */
       for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
-	if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
+	if (TREE_CODE (field) == FIELD_DECL
+	    && TREE_TYPE (field) != error_mark_node
+	    && !DECL_ARTIFICIAL (field))
 	  {
 	    tree field_offset;
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c37b4fe55927..7825c73e0d7e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10530,21 +10530,13 @@ grokdeclarator (const cp_declarator *declarator,
 		 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
 	  {
 	    if (unqualified_id)
-	      error ("field %qD has incomplete type", unqualified_id);
+	      error ("field %qD has incomplete type %qT",
+		     unqualified_id, type);
 	    else
 	      error ("name %qT has incomplete type", type);
 
-	    /* If we're instantiating a template, tell them which
-	       instantiation made the field's type be incomplete.  */
-	    if (current_class_type
-		&& TYPE_NAME (current_class_type)
-		&& IDENTIFIER_TEMPLATE (current_class_name)
-		&& declspecs->type
-		&& declspecs->type == type)
-	      error ("  in instantiation of template %qT",
-		     current_class_type);
-
-	    return error_mark_node;
+	    type = error_mark_node;
+	    decl = NULL_TREE;
 	  }
 	else
 	  {
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 373f88311731..1573cede8992 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -835,9 +835,11 @@ grokfield (const cp_declarator *declarator,
     init = NULL_TREE;
 
   value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
-  if (! value || error_operand_p (value))
+  if (! value || value == error_mark_node)
     /* friend or constructor went bad.  */
     return error_mark_node;
+  if (TREE_TYPE (value) == error_mark_node)
+    return value;
 
   if (TREE_CODE (value) == TYPE_DECL && init)
     {
@@ -1045,8 +1047,10 @@ grokbitfield (const cp_declarator *declarator,
 {
   tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist);
 
-  if (value == error_mark_node) 
+  if (value == error_mark_node)
     return NULL_TREE; /* friends went bad.  */
+  if (TREE_TYPE (value) == error_mark_node)
+    return value;
 
   /* Pass friendly classes back.  */
   if (VOID_TYPE_P (value))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d9a14cc3cbd9..dcdde005cd73 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8863,9 +8863,8 @@ instantiate_class_template_1 (tree type)
 		  else if (TREE_CODE (r) == FIELD_DECL)
 		    {
 		      /* Determine whether R has a valid type and can be
-			 completed later.  If R is invalid, then it is
-			 replaced by error_mark_node so that it will not be
-			 added to TYPE_FIELDS.  */
+			 completed later.  If R is invalid, then its type is
+			 replaced by error_mark_node.  */
 		      tree rtype = TREE_TYPE (r);
 		      if (can_complete_type_without_circularity (rtype))
 			complete_type (rtype);
@@ -8873,7 +8872,7 @@ instantiate_class_template_1 (tree type)
 		      if (!COMPLETE_TYPE_P (rtype))
 			{
 			  cxx_incomplete_type_error (r, rtype);
-			  r = error_mark_node;
+			  TREE_TYPE (r) = error_mark_node;
 			}
 		    }
 
@@ -10514,8 +10513,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
 	/* We don't have to set DECL_CONTEXT here; it is set by
 	   finish_member_declaration.  */
 	DECL_CHAIN (r) = NULL_TREE;
-	if (VOID_TYPE_P (type))
-	  error ("instantiation of %q+D as type %qT", r, type);
 
 	apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
 					args, complain, in_decl);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e0ebae95723d..401904d8ea41 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1236,6 +1236,8 @@ process_init_constructor_record (tree type, tree init,
       type = TREE_TYPE (field);
       if (DECL_BIT_FIELD_TYPE (field))
 	type = DECL_BIT_FIELD_TYPE (field);
+      if (type == error_mark_node)
+	return PICFLAG_ERRONEOUS;
 
       if (idx < vec_safe_length (CONSTRUCTOR_ELTS (init)))
 	{
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
index c735b9e5359c..db5b5c7f3d70 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
@@ -9,11 +9,11 @@ template<class Tp>
     Tp elem;  // { dg-error "incomplete type" }
 
     constexpr single(const Tp& e)
-    : elem(e) { }   // { dg-error "invalid field" }
+    : elem(e) { }
 
     single(single&& s)
     noexcept(std::is_nothrow_move_constructible<Tp>::value) 
-    : elem(s.elem) { } // { dg-error "invalid field|no member" }
+    : elem(s.elem) { }
   };
 
 template<class Tp>
diff --git a/gcc/testsuite/g++.dg/init/array26.C b/gcc/testsuite/g++.dg/init/array26.C
index 83c4e0c4a4d7..f8f3c3743fcf 100644
--- a/gcc/testsuite/g++.dg/init/array26.C
+++ b/gcc/testsuite/g++.dg/init/array26.C
@@ -8,4 +8,4 @@ struct B
   A a; // { dg-error "incomplete type" }
 };
 
-B b[1] = (B[]) { 0 }; // { dg-error "initializer" }
+B b[1] = (B[]) { 0 };
diff --git a/gcc/testsuite/g++.dg/template/error2.C b/gcc/testsuite/g++.dg/template/error2.C
index 96f0bcae6611..be5ab1d450ed 100644
--- a/gcc/testsuite/g++.dg/template/error2.C
+++ b/gcc/testsuite/g++.dg/template/error2.C
@@ -7,9 +7,8 @@
 
 template<class T> struct X
 {
-  T m;	// { dg-error "as type 'void'" "void" }
-	// { dg-error "incomplete type" "incomplate" { target *-*-* } 10 }
-	// { dg-error "invalid" "invalid" { target *-*-* } 10 }
+  T m;	// { dg-error "void" "void" }
+	// { dg-error "incomplete type" "incomplete" { target *-*-* } 10 }
 };
 
 template<class T >
diff --git a/gcc/testsuite/g++.dg/template/instantiate3.C b/gcc/testsuite/g++.dg/template/instantiate3.C
index 0e9fd706015c..c0754da92272 100644
--- a/gcc/testsuite/g++.dg/template/instantiate3.C
+++ b/gcc/testsuite/g++.dg/template/instantiate3.C
@@ -10,7 +10,7 @@ template <class TYPE>
 struct ACE_Cleanup_Adapter
 {
   TYPE &object ()
-  { return object_; }	// { dg-error "invalid" }
+  { return object_; }
   TYPE object_;		// { dg-error "incomplete type" }
 };
 
-- 
GitLab