diff options
author | Joseph Myers <josmyers@redhat.com> | 2024-10-23 00:10:01 +0000 |
---|---|---|
committer | Joseph Myers <josmyers@redhat.com> | 2024-10-23 00:10:01 +0000 |
commit | ecb55d94738b1ed36fa76d02e3454cc4959a141d (patch) | |
tree | a3699287a1353ba0ac5b821208fc36194518ebfb /gcc | |
parent | 71e13ea134b04562f8f2cdd9c4a55dbb0905f96a (diff) | |
download | gcc-ecb55d94738b1ed36fa76d02e3454cc4959a141d.zip gcc-ecb55d94738b1ed36fa76d02e3454cc4959a141d.tar.gz gcc-ecb55d94738b1ed36fa76d02e3454cc4959a141d.tar.bz2 |
c: Restore "originally defined" struct redefinition messages for C23
One failure with a -std=gnu23 default that indicates a
quality-of-implementation regression in C23 mode is gcc.dg/pr39084.c,
which loses the expected "originally defined here" message on struct
redefinition errors (which occur in a different place in the front end
for C23 because it is necessary to see the members of the struct to
determine whether the redefinition is valid). That message seems a
good thing to have both in and out of C23 mode, so add logic to
restore it in the C23 case.
Bootstrapped with no regressions for x86-64-pc-linux-gnu.
gcc/c/
* c-decl.cc (c_struct_parse_info): Add member refloc.
(start_struct): Store refloc in struct_parse_info.
(finish_struct): Give "originally defined" message for C23 struct
redefinition errors.
gcc/testsuite/
* gcc.dg/gnu17-tag-1.c, gcc.dg/gnu23-tag-5.c: New tests.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c/c-decl.cc | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gnu17-tag-1.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gnu23-tag-5.c | 13 |
3 files changed, 40 insertions, 3 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 3733ecf..047158e 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -640,6 +640,8 @@ public: /* If warn_cxx_compat, a list of typedef names used when defining fields in this struct. */ auto_vec<tree> typedefs_seen; + /* The location of a previous definition of this struct. */ + location_t refloc; }; @@ -9000,6 +9002,7 @@ start_struct (location_t loc, enum tree_code code, tree name, *enclosing_struct_parse_info = struct_parse_info; struct_parse_info = new c_struct_parse_info (); + struct_parse_info->refloc = refloc; /* FIXME: This will issue a warning for a use of a type defined within a statement expr used within sizeof, et. al. This is not @@ -9896,10 +9899,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, { TYPE_STUB_DECL (vistype) = TYPE_STUB_DECL (t); if (c_type_variably_modified_p (t)) - error ("redefinition of struct or union %qT with variably " - "modified type", t); + { + error ("redefinition of struct or union %qT with variably " + "modified type", t); + if (struct_parse_info->refloc != UNKNOWN_LOCATION) + inform (struct_parse_info->refloc, "originally defined here"); + } else if (!comptypes_same_p (t, vistype)) - error ("redefinition of struct or union %qT", t); + { + error ("redefinition of struct or union %qT", t); + if (struct_parse_info->refloc != UNKNOWN_LOCATION) + inform (struct_parse_info->refloc, "originally defined here"); + } } } diff --git a/gcc/testsuite/gcc.dg/gnu17-tag-1.c b/gcc/testsuite/gcc.dg/gnu17-tag-1.c new file mode 100644 index 0000000..2c548aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu17-tag-1.c @@ -0,0 +1,13 @@ +/* Test "originally defined" message for struct redefinition for C17. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu17" } */ + +struct s { int i; }; /* { dg-message "originally defined" } */ +struct s { int j; }; /* { dg-error "redefinition" } */ + +void +f (int x) +{ + struct t { int (*a)[x]; }; /* { dg-message "originally defined" } */ + struct t { int (*a)[x]; }; /* { dg-error "redefinition" } */ +} diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-5.c b/gcc/testsuite/gcc.dg/gnu23-tag-5.c new file mode 100644 index 0000000..bb5670e --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu23-tag-5.c @@ -0,0 +1,13 @@ +/* Test "originally defined" message for struct redefinition for C23. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23" } */ + +struct s { int i; }; /* { dg-message "originally defined" } */ +struct s { int j; }; /* { dg-error "redefinition" } */ + +void +f (int x) +{ + struct t { int (*a)[x]; }; /* { dg-message "originally defined" } */ + struct t { int (*a)[x]; }; /* { dg-error "redefinition" } */ +} |