aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <josmyers@redhat.com>2024-10-23 00:10:01 +0000
committerJoseph Myers <josmyers@redhat.com>2024-10-23 00:10:01 +0000
commitecb55d94738b1ed36fa76d02e3454cc4959a141d (patch)
treea3699287a1353ba0ac5b821208fc36194518ebfb /gcc
parent71e13ea134b04562f8f2cdd9c4a55dbb0905f96a (diff)
downloadgcc-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.cc17
-rw-r--r--gcc/testsuite/gcc.dg/gnu17-tag-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/gnu23-tag-5.c13
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" } */
+}