diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 3733ecfc13fc4d49c6cd9ab801bbc0e89ce49113..047158eef9d00018270cfe8f85f995960ff53644 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 0000000000000000000000000000000000000000..2c548aa50f4fd9f017415fe8682b6235c34bfdf2
--- /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 0000000000000000000000000000000000000000..bb5670e20bb38603b255fc5ffe9e63190167c73d
--- /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" } */
+}