diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f8bacf5d42ba4f27de7f661363efc18b1e950096..c53a9ff0b5a0df639a119e0bfac34530f1d88198 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 40e6d3eed73d19c3825c420b2437cb9ed247f79a..286164d020294ef7b2f8fd4554698c0b26400807 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 c37b4fe55927115082f04813ccc77eeac81844f6..7825c73e0d7e061f3d41ac33a08fc5f9b1866940 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 373f883117315963fd64dce3a80c9ed88bef09c2..1573cede8992a5a2e9188af6514e2bd91905c61b 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 d9a14cc3cbd95c820f0a9e2540ce8b8ba19e6661..dcdde005cd73d8bb47d3cf9f0a27d46f607950bb 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 e0ebae95723dce020b6e37f7b4533a747c7b9325..401904d8ea41e9f535f9a089bfab65fa67b6cc7a 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 c735b9e5359c5c6adea7c8d7c4f7edde055e6157..db5b5c7f3d70186951ca95d0dd3170c14e8be55f 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 83c4e0c4a4d77533c1aeba9aee44235eb45bf9d0..f8f3c3743fcfd9da8970b1022209d1a0fadc7ecd 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 96f0bcae66110c82abcf8c3f54f335e49195796c..be5ab1d450ed02038c451f7f40f6a1d9a4197607 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 0e9fd706015c1e70214614c428ca14446dc1f277..c0754da92272b18d56030c9cdfe37b6ce4cba06a 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" } };