Commit e765a228 by Jason Merrill Committed by Jason Merrill

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
parent 73310b0e
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> 2013-06-05 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51908 PR c++/51908
......
...@@ -3779,7 +3779,9 @@ walk_subobject_offsets (tree type, ...@@ -3779,7 +3779,9 @@ walk_subobject_offsets (tree type,
/* Iterate through the fields of TYPE. */ /* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 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; tree field_offset;
......
...@@ -10530,21 +10530,13 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -10530,21 +10530,13 @@ grokdeclarator (const cp_declarator *declarator,
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{ {
if (unqualified_id) if (unqualified_id)
error ("field %qD has incomplete type", unqualified_id); error ("field %qD has incomplete type %qT",
unqualified_id, type);
else else
error ("name %qT has incomplete type", type); error ("name %qT has incomplete type", type);
/* If we're instantiating a template, tell them which type = error_mark_node;
instantiation made the field's type be incomplete. */ decl = NULL_TREE;
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;
} }
else else
{ {
......
...@@ -835,9 +835,11 @@ grokfield (const cp_declarator *declarator, ...@@ -835,9 +835,11 @@ grokfield (const cp_declarator *declarator,
init = NULL_TREE; init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist); 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. */ /* friend or constructor went bad. */
return error_mark_node; return error_mark_node;
if (TREE_TYPE (value) == error_mark_node)
return value;
if (TREE_CODE (value) == TYPE_DECL && init) if (TREE_CODE (value) == TYPE_DECL && init)
{ {
...@@ -1045,8 +1047,10 @@ grokbitfield (const cp_declarator *declarator, ...@@ -1045,8 +1047,10 @@ grokbitfield (const cp_declarator *declarator,
{ {
tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist); tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist);
if (value == error_mark_node) if (value == error_mark_node)
return NULL_TREE; /* friends went bad. */ return NULL_TREE; /* friends went bad. */
if (TREE_TYPE (value) == error_mark_node)
return value;
/* Pass friendly classes back. */ /* Pass friendly classes back. */
if (VOID_TYPE_P (value)) if (VOID_TYPE_P (value))
......
...@@ -8863,9 +8863,8 @@ instantiate_class_template_1 (tree type) ...@@ -8863,9 +8863,8 @@ instantiate_class_template_1 (tree type)
else if (TREE_CODE (r) == FIELD_DECL) else if (TREE_CODE (r) == FIELD_DECL)
{ {
/* Determine whether R has a valid type and can be /* Determine whether R has a valid type and can be
completed later. If R is invalid, then it is completed later. If R is invalid, then its type is
replaced by error_mark_node so that it will not be replaced by error_mark_node. */
added to TYPE_FIELDS. */
tree rtype = TREE_TYPE (r); tree rtype = TREE_TYPE (r);
if (can_complete_type_without_circularity (rtype)) if (can_complete_type_without_circularity (rtype))
complete_type (rtype); complete_type (rtype);
...@@ -8873,7 +8872,7 @@ instantiate_class_template_1 (tree type) ...@@ -8873,7 +8872,7 @@ instantiate_class_template_1 (tree type)
if (!COMPLETE_TYPE_P (rtype)) if (!COMPLETE_TYPE_P (rtype))
{ {
cxx_incomplete_type_error (r, 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) ...@@ -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 /* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */ finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE; 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, apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
args, complain, in_decl); args, complain, in_decl);
......
...@@ -1236,6 +1236,8 @@ process_init_constructor_record (tree type, tree init, ...@@ -1236,6 +1236,8 @@ process_init_constructor_record (tree type, tree init,
type = TREE_TYPE (field); type = TREE_TYPE (field);
if (DECL_BIT_FIELD_TYPE (field)) if (DECL_BIT_FIELD_TYPE (field))
type = 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))) if (idx < vec_safe_length (CONSTRUCTOR_ELTS (init)))
{ {
......
...@@ -9,11 +9,11 @@ template<class Tp> ...@@ -9,11 +9,11 @@ template<class Tp>
Tp elem; // { dg-error "incomplete type" } Tp elem; // { dg-error "incomplete type" }
constexpr single(const Tp& e) constexpr single(const Tp& e)
: elem(e) { } // { dg-error "invalid field" } : elem(e) { }
single(single&& s) single(single&& s)
noexcept(std::is_nothrow_move_constructible<Tp>::value) noexcept(std::is_nothrow_move_constructible<Tp>::value)
: elem(s.elem) { } // { dg-error "invalid field|no member" } : elem(s.elem) { }
}; };
template<class Tp> template<class Tp>
......
...@@ -8,4 +8,4 @@ struct B ...@@ -8,4 +8,4 @@ struct B
A a; // { dg-error "incomplete type" } A a; // { dg-error "incomplete type" }
}; };
B b[1] = (B[]) { 0 }; // { dg-error "initializer" } B b[1] = (B[]) { 0 };
...@@ -7,9 +7,8 @@ ...@@ -7,9 +7,8 @@
template<class T> struct X template<class T> struct X
{ {
T m; // { dg-error "as type 'void'" "void" } T m; // { dg-error "void" "void" }
// { dg-error "incomplete type" "incomplate" { target *-*-* } 10 } // { dg-error "incomplete type" "incomplete" { target *-*-* } 10 }
// { dg-error "invalid" "invalid" { target *-*-* } 10 }
}; };
template<class T > template<class T >
......
...@@ -10,7 +10,7 @@ template <class TYPE> ...@@ -10,7 +10,7 @@ template <class TYPE>
struct ACE_Cleanup_Adapter struct ACE_Cleanup_Adapter
{ {
TYPE &object () TYPE &object ()
{ return object_; } // { dg-error "invalid" } { return object_; }
TYPE object_; // { dg-error "incomplete type" } TYPE object_; // { dg-error "incomplete type" }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment