From patchwork Thu Dec 9 20:35:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 74988 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 691A8B70A5 for ; Fri, 10 Dec 2010 07:36:00 +1100 (EST) Received: (qmail 13546 invoked by alias); 9 Dec 2010 20:35:58 -0000 Received: (qmail 13093 invoked by uid 22791); 9 Dec 2010 20:35:53 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 09 Dec 2010 20:35:46 +0000 Received: (qmail 13096 invoked from network); 9 Dec 2010 20:35:42 -0000 Received: from unknown (HELO codesourcery.com) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 9 Dec 2010 20:35:42 -0000 Date: Thu, 9 Dec 2010 15:35:39 -0500 From: Nathan Froyd To: gcc-patches@gcc.gnu.org Subject: [PATCH] mostly unify readonly_error in C and C++ front-ends Message-ID: <20101209203538.GP25904@nightcrawler> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch introduces a common readonly_error function that can be used by the C and C++ front-ends along with associated tweaks to make it work right. Notably, the C++-specific readonly_error_kind goes away, subsumed by lvalue_use, and the C++ readonly_error function is renamed to cp_readonly_error to handle a few C++-specific cases. I thought the C++ wording was better in most cases, though the "used as `asm' output" phrasing that the C front-end uses is preferable to "(via 'asm' output)", I think. I also think the greater number of cases handled by the C++ front-end and the more precise wording will be useful in the C front-end. Tested on x86_64-unknown-linux-gnu. OK to commit? -Nathan gcc/ * c-typeck.c (readonly_error): Delete. gcc/c-family/ * c-common.h (readonly_error): Declare. * c-common.c (readonly_error): Define. gcc/cp/ * cp-tree.h (readonly_error_kind): Delete. (readonly_error): Rename to... (cp_readonly_error): ...this. Change second argument to be an enum lvalue_use. * semantics.c (finish_asm_stmt): Call cp_readonly_error. * typeck.c (cp_build_unary_op): Likewise. (cp_build_modify_expr): Likewise. * typeck2.c (readonly_error): Rename to... (cp_readonly_error): ...this. Delegate to readonly_error for most cases. gcc/testsuite/ * gcc.dg/dfp/struct-union.c: Adjust. * gcc.dg/lvalue-2.c: Adjust. * gcc.dg/pr21419.c: Adjust. * gcc.dg/qual-component-1.c: Adjust. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 7a57838..4cf6877 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8558,6 +8558,75 @@ warn_for_omitted_condop (location_t location, tree cond) "suggest explicit middle operand"); } +/* Give an error for storing into ARG, which is 'const'. USE indicates + how ARG was being used. */ + +void +readonly_error (tree arg, enum lvalue_use use) +{ + gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement + || use == lv_asm); + /* Using this macro rather than (for example) arrays of messages + ensures that all the format strings are checked at compile + time. */ +#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \ + : (use == lv_increment ? (I) \ + : (use == lv_decrement ? (D) : (AS)))) + if (TREE_CODE (arg) == COMPONENT_REF) + { + if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) + error (READONLY_MSG (G_("assignment of member " + "%qD in read-only structure"), + G_("increment of member " + "%qD in read-only structure"), + G_("decrement of member " + "%qD in read-only structure"), + G_("member %qD in read-only structure " + "used as % output")), + TREE_OPERAND (arg, 1)); + else + error (READONLY_MSG (G_("assignment of read-only member %qD"), + G_("increment of read-only member %qD"), + G_("decrement of read-only member %qD"), + G_("read-only member %qD used as % output")), + TREE_OPERAND (arg, 1)); + } + else if (TREE_CODE (arg) == VAR_DECL) + error (READONLY_MSG (G_("assignment of read-only variable %qD"), + G_("increment of read-only variable %qD"), + G_("decrement of read-only variable %qD"), + G_("read-only variable %qD used as % output")), + arg); + else if (TREE_CODE (arg) == PARM_DECL) + error (READONLY_MSG (G_("assignment of read-only parameter %qD"), + G_("increment of read-only parameter %qD"), + G_("decrement of read-only parameter %qD"), + G_("read-only parameter %qD use as % output")), + arg); + else if (TREE_CODE (arg) == RESULT_DECL) + error (READONLY_MSG (G_("assignment of " + "read-only named return value %qD"), + G_("increment of " + "read-only named return value %qD"), + G_("decrement of " + "read-only named return value %qD"), + G_("read-only named return value %qD " + "used as %output")), + arg); + else if (TREE_CODE (arg) == FUNCTION_DECL) + error (READONLY_MSG (G_("assignment of function %qD"), + G_("increment of function %qD"), + G_("decrement of function %qD"), + G_("function %qD used as % output")), + arg); + else + error (READONLY_MSG (G_("assignment of read-only location %qE"), + G_("increment of read-only location %qE"), + G_("decrement of read-only location %qE"), + G_("read-only location %qE used as % output")), + arg); +} + /* Print an error message for an invalid lvalue. USE says how the lvalue is being used and so selects the error message. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 928e502..eabf913 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -928,6 +928,7 @@ enum lvalue_use { lv_asm }; +extern void readonly_error (tree, enum lvalue_use); extern void lvalue_error (enum lvalue_use); extern int complete_array_type (tree *, tree, bool); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 7bba44e..9de5332 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -97,7 +97,6 @@ static void add_pending_init (tree, tree, tree, bool, struct obstack *); static void set_nonincremental_init (struct obstack *); static void set_nonincremental_init_from_string (tree, struct obstack *); static tree find_init_member (tree, struct obstack *); -static void readonly_error (tree, enum lvalue_use); static void readonly_warning (tree, enum lvalue_use); static int lvalue_or_else (const_tree, enum lvalue_use); static void record_maybe_used_decl (tree); @@ -3898,44 +3897,6 @@ lvalue_p (const_tree ref) } } -/* Give an error for storing in something that is 'const'. */ - -static void -readonly_error (tree arg, enum lvalue_use use) -{ - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \ - : (use == lv_increment ? (I) \ - : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) - { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - readonly_error (TREE_OPERAND (arg, 0), use); - else - error (READONLY_MSG (G_("assignment of read-only member %qD"), - G_("increment of read-only member %qD"), - G_("decrement of read-only member %qD"), - G_("read-only member %qD used as % output")), - TREE_OPERAND (arg, 1)); - } - else if (TREE_CODE (arg) == VAR_DECL) - error (READONLY_MSG (G_("assignment of read-only variable %qD"), - G_("increment of read-only variable %qD"), - G_("decrement of read-only variable %qD"), - G_("read-only variable %qD used as % output")), - arg); - else - error (READONLY_MSG (G_("assignment of read-only location %qE"), - G_("increment of read-only location %qE"), - G_("decrement of read-only location %qE"), - G_("read-only location %qE used as % output")), - arg); -} - /* Give a warning for storing in something that is read-only in GCC terms but not const in ISO C terms. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 03c02fc..f9db828 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -406,19 +406,6 @@ typedef enum composite_pointer_operation CPO_CONDITIONAL_EXPR } composite_pointer_operation; -/* The various readonly error string used by readonly_error. */ -typedef enum readonly_error_kind -{ - /* assignment */ - REK_ASSIGNMENT, - /* assignment (via 'asm' output) */ - REK_ASSIGNMENT_ASM, - /* increment */ - REK_INCREMENT, - /* decrement */ - REK_DECREMENT -} readonly_error_kind; - /* Possible cases of expression list used by build_x_compound_expr_from_list. */ typedef enum expr_list_kind { ELK_INIT, /* initializer */ @@ -5589,7 +5576,7 @@ extern void cxx_incomplete_type_error (const_tree, const_tree); (cxx_incomplete_type_diagnostic ((V), (T), DK_ERROR)) extern tree error_not_base_type (tree, tree); extern tree binfo_or_else (tree, tree); -extern void readonly_error (tree, readonly_error_kind); +extern void cp_readonly_error (tree, enum lvalue_use); extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index db0d0a1..368dc7f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1317,7 +1317,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, effectively const. */ || (CLASS_TYPE_P (TREE_TYPE (operand)) && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) - readonly_error (operand, REK_ASSIGNMENT_ASM); + cp_readonly_error (operand, lv_asm); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); oconstraints[i] = constraint; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 7416f09..a2192a7 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5158,9 +5158,9 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, || TREE_READONLY (arg)) { if (complain & tf_error) - readonly_error (arg, ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? REK_INCREMENT : REK_DECREMENT)); + cp_readonly_error (arg, ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? lv_increment : lv_decrement)); else return error_mark_node; } @@ -6703,7 +6703,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, && C_TYPE_FIELDS_READONLY (lhstype)))) { if (complain & tf_error) - readonly_error (lhs, REK_ASSIGNMENT); + cp_readonly_error (lhs, lv_assign); else return error_mark_node; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 1c05314..632348d 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -70,7 +70,7 @@ binfo_or_else (tree base, tree type) value may not be changed thereafter. */ void -readonly_error (tree arg, readonly_error_kind errstring) +cp_readonly_error (tree arg, enum lvalue_use errstring) { /* This macro is used to emit diagnostics to ensure that all format @@ -81,16 +81,16 @@ readonly_error (tree arg, readonly_error_kind errstring) do { \ switch (errstring) \ { \ - case REK_ASSIGNMENT: \ + case lv_assign: \ error(AS, ARG); \ break; \ - case REK_ASSIGNMENT_ASM: \ + case lv_asm: \ error(ASM, ARG); \ break; \ - case REK_INCREMENT: \ + case lv_increment: \ error (IN, ARG); \ break; \ - case REK_DECREMENT: \ + case lv_decrement: \ error (DE, ARG); \ break; \ default: \ @@ -98,108 +98,36 @@ readonly_error (tree arg, readonly_error_kind errstring) } \ } while (0) - if (TREE_CODE (arg) == COMPONENT_REF) - { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "data-member %qD in read-only structure"), - G_("assignment (via 'asm' output) of " - "data-member %qD in read-only structure"), - G_("increment of " - "data-member %qD in read-only structure"), - G_("decrement of " - "data-member %qD in read-only structure"), - TREE_OPERAND (arg, 1)); - else - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "read-only data-member %qD"), - G_("assignment (via 'asm' output) of " - "read-only data-member %qD"), - G_("increment of " - "read-only data-member %qD"), - G_("decrement of " - "read-only data-member %qD"), - TREE_OPERAND (arg, 1)); - } - else if (TREE_CODE (arg) == VAR_DECL) - { - if (DECL_LANG_SPECIFIC (arg) - && DECL_IN_AGGR_P (arg) - && !TREE_STATIC (arg)) - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "constant field %qD"), - G_("assignment (via 'asm' output) of " - "constant field %qD"), - G_("increment of " - "constant field %qD"), - G_("decrement of " - "constant field %qD"), - arg); - else - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "read-only variable %qD"), - G_("assignment (via 'asm' output) of " - "read-only variable %qD"), - G_("increment of " - "read-only variable %qD"), - G_("decrement of " - "read-only variable %qD"), - arg); + /* Handle C++-specific things first. */ - } - else if (TREE_CODE (arg) == PARM_DECL) + if (TREE_CODE (arg) == VAR_DECL + && DECL_LANG_SPECIFIC (arg) + && DECL_IN_AGGR_P (arg) + && !TREE_STATIC (arg)) ERROR_FOR_ASSIGNMENT (G_("assignment of " - "read-only parameter %qD"), - G_("assignment (via 'asm' output) of " - "read-only parameter %qD"), - G_("increment of " - "read-only parameter %qD"), - G_("decrement of " - "read-only parameter %qD"), - arg); + "constant field %qD"), + G_("constant field %qD " + "used as % output"), + G_("increment of " + "constant field %qD"), + G_("decrement of " + "constant field %qD"), + arg); else if (TREE_CODE (arg) == INDIRECT_REF && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL)) ERROR_FOR_ASSIGNMENT (G_("assignment of " "read-only reference %qD"), - G_("assignment (via 'asm' output) of " - "read-only reference %qD"), + G_("read-only reference %qD " + "used as % output"), G_("increment of " "read-only reference %qD"), G_("decrement of " "read-only reference %qD"), TREE_OPERAND (arg, 0)); - else if (TREE_CODE (arg) == RESULT_DECL) - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "read-only named return value %qD"), - G_("assignment (via 'asm' output) of " - "read-only named return value %qD"), - G_("increment of " - "read-only named return value %qD"), - G_("decrement of " - "read-only named return value %qD"), - arg); - else if (TREE_CODE (arg) == FUNCTION_DECL) - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "function %qD"), - G_("assignment (via 'asm' output) of " - "function %qD"), - G_("increment of " - "function %qD"), - G_("decrement of " - "function %qD"), - arg); else - ERROR_FOR_ASSIGNMENT (G_("assignment of " - "read-only location %qE"), - G_("assignment (via 'asm' output) of " - "read-only location %qE"), - G_("increment of " - "read-only location %qE"), - G_("decrement of " - "read-only location %qE"), - arg); + readonly_error (arg, errstring); } diff --git a/gcc/testsuite/gcc.dg/dfp/struct-union.c b/gcc/testsuite/gcc.dg/dfp/struct-union.c index 8858926..e236b8a 100644 --- a/gcc/testsuite/gcc.dg/dfp/struct-union.c +++ b/gcc/testsuite/gcc.dg/dfp/struct-union.c @@ -33,22 +33,22 @@ union u h (union u u) void f() { - cs.d32 = 1.23dd; /* { dg-error "assignment of read-only variable" } */ - cs.d64 = 1.23df; /* { dg-error "assignment of read-only variable" } */ + cs.d32 = 1.23dd; /* { dg-error "assignment of member 'd32' in read-only structure" } */ + cs.d64 = 1.23df; /* { dg-error "assignment of member 'd64' in read-only structure" } */ s.d64 = 1.23df; /* { dg-error "assignment of read-only member" } */ s.d32 = 1.23dd; u.d32 = 1.23dd; u.d64 = 1.23df; /* { dg-error "assignment of read-only member" } */ - u.cs.d32 = 1.23dd; /* { dg-error "assignment of read-only member" } */ - u.cs.d64 = 1.23df; /* { dg-error "assignment of read-only member" } */ + u.cs.d32 = 1.23dd; /* { dg-error "assignment of member 'd32' in read-only structure" } */ + u.cs.d64 = 1.23df; /* { dg-error "assignment of member 'd64' in read-only structure" } */ - cu.d32 = 1.23dd; /* { dg-error "assignment of read-only variable" } */ + cu.d32 = 1.23dd; /* { dg-error "assignment of member 'd32' in read-only structure" } */ - cu.d64 = 1.23df; /* { dg-error "assignment of read-only variable" } */ - cu.cs.d32 = 1.23dd; /* { dg-error "assignment of read-only variable" } */ - cu.cs.d64 = 1.23df; /* { dg-error "assignment of read-only variable" } */ + cu.d64 = 1.23df; /* { dg-error "assignment of member 'd64' in read-only structure" } */ + cu.cs.d32 = 1.23dd; /* { dg-error "assignment of member 'd32' in read-only structure" } */ + cu.cs.d64 = 1.23df; /* { dg-error "assignment of member 'd64' in read-only structure" } */ /* f().x is a valid postfix expression but is not an lvalue if function f() returning a structure or union. */ diff --git a/gcc/testsuite/gcc.dg/lvalue-2.c b/gcc/testsuite/gcc.dg/lvalue-2.c index a6f8809..32c98bf 100644 --- a/gcc/testsuite/gcc.dg/lvalue-2.c +++ b/gcc/testsuite/gcc.dg/lvalue-2.c @@ -26,23 +26,23 @@ void f1 (void) { c = 1; /* { dg-error "assignment of read-only variable 'c'" } */ - d.x = 1; /* { dg-error "assignment of read-only variable 'd'" } */ + d.x = 1; /* { dg-error "assignment of member 'x' in read-only structure" } */ e.x = 1; /* { dg-error "assignment of read-only member 'x'" } */ *f = 1; /* { dg-error "assignment of read-only location" } */ c++; /* { dg-error "increment of read-only variable 'c'" } */ - d.x++; /* { dg-error "increment of read-only variable 'd'" } */ + d.x++; /* { dg-error "increment of member 'x' in read-only structure" } */ e.x++; /* { dg-error "increment of read-only member 'x'" } */ (*f)++; /* { dg-error "increment of read-only location" } */ ++c; /* { dg-error "increment of read-only variable 'c'" } */ - ++d.x; /* { dg-error "increment of read-only variable 'd'" } */ + ++d.x; /* { dg-error "increment of member 'x' in read-only structure" } */ ++e.x; /* { dg-error "increment of read-only member 'x'" } */ ++(*f); /* { dg-error "increment of read-only location" } */ c--; /* { dg-error "decrement of read-only variable 'c'" } */ - d.x--; /* { dg-error "decrement of read-only variable 'd'" } */ + d.x--; /* { dg-error "decrement of member 'x' in read-only structure" } */ e.x--; /* { dg-error "decrement of read-only member 'x'" } */ (*f)--; /* { dg-error "decrement of read-only location" } */ --c; /* { dg-error "decrement of read-only variable 'c'" } */ - --d.x; /* { dg-error "decrement of read-only variable 'd'" } */ + --d.x; /* { dg-error "decrement of member 'x' in read-only structure" } */ --e.x; /* { dg-error "decrement of read-only member 'x'" } */ --(*f); /* { dg-error "decrement of read-only location" } */ } diff --git a/gcc/testsuite/gcc.dg/pr21419.c b/gcc/testsuite/gcc.dg/pr21419.c index dc8f602..120ed7f 100644 --- a/gcc/testsuite/gcc.dg/pr21419.c +++ b/gcc/testsuite/gcc.dg/pr21419.c @@ -9,7 +9,7 @@ void f(void) void g(const int set) { - __asm__ __volatile__ ("" : "=r" (set)); /* { dg-error "read-only location" } */ + __asm__ __volatile__ ("" : "=r" (set)); /* { dg-error "read-only parameter" } */ } diff --git a/gcc/testsuite/gcc.dg/qual-component-1.c b/gcc/testsuite/gcc.dg/qual-component-1.c index dbf6115..dedc63f 100644 --- a/gcc/testsuite/gcc.dg/qual-component-1.c +++ b/gcc/testsuite/gcc.dg/qual-component-1.c @@ -62,39 +62,39 @@ f (void) *v2->f[0] = 0; /* { dg-error "assignment of read-only" } */ **v2->f = 0; /* { dg-error "assignment of read-only" } */ - v3->a = 0; /* { dg-error "assignment of read-only" } */ + v3->a = 0; /* { dg-error "assignment of member" } */ v3->b[0] = 0; /* { dg-error "assignment of read-only" } */ *v3->b = 0; /* { dg-error "assignment of read-only" } */ v3->c[0][0] = 0; /* { dg-error "assignment of read-only" } */ *v3->c[0] = 0; /* { dg-error "assignment of read-only" } */ **v3->c = 0; /* { dg-error "assignment of read-only" } */ - v3->d = 0; /* { dg-error "assignment of read-only" } */ + v3->d = 0; /* { dg-error "assignment of member" } */ v3->e[0] = 0; /* { dg-error "assignment of read-only" } */ *v3->e = 0; /* { dg-error "assignment of read-only" } */ v3->f[0][0] = 0; /* { dg-error "assignment of read-only" } */ *v3->f[0] = 0; /* { dg-error "assignment of read-only" } */ **v3->f = 0; /* { dg-error "assignment of read-only" } */ - v4.a = 0; /* { dg-error "assignment of read-only" } */ + v4.a = 0; /* { dg-error "assignment of member" } */ v4.b[0] = 0; /* { dg-error "assignment of read-only" } */ *v4.b = 0; /* { dg-error "assignment of read-only" } */ v4.c[0][0] = 0; /* { dg-error "assignment of read-only" } */ *v4.c[0] = 0; /* { dg-error "assignment of read-only" } */ **v4.c = 0; /* { dg-error "assignment of read-only" } */ - v4.d = 0; /* { dg-error "assignment of read-only" } */ + v4.d = 0; /* { dg-error "assignment of member" } */ v4.e[0] = 0; /* { dg-error "assignment of read-only" } */ *v4.e = 0; /* { dg-error "assignment of read-only" } */ v4.f[0][0] = 0; /* { dg-error "assignment of read-only" } */ *v4.f[0] = 0; /* { dg-error "assignment of read-only" } */ **v4.f = 0; /* { dg-error "assignment of read-only" } */ - v5.x.a = 0; /* { dg-error "assignment of read-only" } */ + v5.x.a = 0; /* { dg-error "assignment of member" } */ v5.x.b[0] = 0; /* { dg-error "assignment of read-only" } */ *v5.x.b = 0; /* { dg-error "assignment of read-only" } */ v5.x.c[0][0] = 0; /* { dg-error "assignment of read-only" } */ *v5.x.c[0] = 0; /* { dg-error "assignment of read-only" } */ **v5.x.c = 0; /* { dg-error "assignment of read-only" } */ - v5.x.d = 0; /* { dg-error "assignment of read-only" } */ + v5.x.d = 0; /* { dg-error "assignment of member" } */ v5.x.e[0] = 0; /* { dg-error "assignment of read-only" } */ *v5.x.e = 0; /* { dg-error "assignment of read-only" } */ v5.x.f[0][0] = 0; /* { dg-error "assignment of read-only" } */