public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Uecker <uecker@tugraz.at>
To: gcc-patches@gcc.gnu.org
Cc: Joseph Myers <joseph@codesourcery.com>
Subject: [V4] [C PATCH 1/4] c23: tag compatibility rules for struct and unions
Date: Mon, 27 Nov 2023 14:16:29 +0100	[thread overview]
Message-ID: <85008511e64113eaf86afa8b546ed55fd3620177.camel@tugraz.at> (raw)
In-Reply-To: <02a9b94e4d653b6f1b9f89a1b62187f46e871738.camel@tugraz.at>


Note that there is an additional change in parser_xref_tag
to address the issue regarding completeness in redefinition
which affects also structs / unions.  The test c23-tag-6.c
was changed accordingly.


c23: tag compatibility rules for struct and unions

Implement redeclaration and compatibility rules for
structures and unions in C23.

gcc/c/:
	* c-decl.cc (previous_tag): New function.
	(parser_xref_tag): Find earlier definition.
	(get_parm_info): Turn off warning for C23.
	(start_struct): Allow redefinitons.
	(finish_struct): Diagnose conflicts.
	* c-tree.h (comptypes_same_p): Add prototype.
	* c-typeck.cc (comptypes_same_p): New function
	(comptypes_internal): Activate comparison of tagged types.
	(convert_for_assignment): Ignore qualifiers.
	(digest_init): Add error.
	(initialized_elementwise_p): Allow compatible types.

gcc/testsuite/:
	* gcc.dg/c23-enum-7.c: Remove warning.
	* gcc.dg/c23-tag-1.c: New test.
	* gcc.dg/c23-tag-2.c: New deactivated test.
	* gcc.dg/c23-tag-3.c: New test.
	* gcc.dg/c23-tag-4.c: New test.
	* gcc.dg/c23-tag-5.c: New deactivated test.
	* gcc.dg/c23-tag-6.c: New test.
	* gcc.dg/c23-tag-7.c: New test.
	* gcc.dg/c23-tag-8.c: New test.
	* gcc.dg/gnu23-tag-1.c: New test.
	* gcc.dg/gnu23-tag-2.c: New test.
	* gcc.dg/gnu23-tag-3.c: New test.
	* gcc.dg/gnu23-tag-4.c: New test.
---
 gcc/c/c-decl.cc                    | 72 +++++++++++++++++++++++++++---
 gcc/c/c-tree.h                     |  1 +
 gcc/c/c-typeck.cc                  | 38 +++++++++++++---
 gcc/testsuite/gcc.dg/c23-enum-7.c  |  6 +--
 gcc/testsuite/gcc.dg/c23-tag-1.c   | 67 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c23-tag-2.c   | 43 ++++++++++++++++++
 gcc/testsuite/gcc.dg/c23-tag-3.c   | 16 +++++++
 gcc/testsuite/gcc.dg/c23-tag-4.c   | 26 +++++++++++
 gcc/testsuite/gcc.dg/c23-tag-5.c   | 33 ++++++++++++++
 gcc/testsuite/gcc.dg/c23-tag-6.c   | 58 ++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/c23-tag-7.c   | 12 +++++
 gcc/testsuite/gcc.dg/c23-tag-8.c   | 10 +++++
 gcc/testsuite/gcc.dg/gnu23-tag-1.c | 10 +++++
 gcc/testsuite/gcc.dg/gnu23-tag-2.c | 19 ++++++++
 gcc/testsuite/gcc.dg/gnu23-tag-3.c | 28 ++++++++++++
 gcc/testsuite/gcc.dg/gnu23-tag-4.c | 31 +++++++++++++
 16 files changed, 454 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-1.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-2.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-3.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-4.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-5.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-6.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-7.c
 create mode 100644 gcc/testsuite/gcc.dg/c23-tag-8.c
 create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-1.c
 create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-2.c
 create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-3.c
 create mode 100644 gcc/testsuite/gcc.dg/gnu23-tag-4.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 64d3a941cb9..ebe1708b977 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -2039,6 +2039,28 @@ locate_old_decl (tree decl)
 	    decl, TREE_TYPE (decl));
 }
 
+
+/* Helper function.  For a tagged type, it finds the declaration
+   for a visible tag declared in the the same scope if such a
+   declaration exists.  */
+static tree
+previous_tag (tree type)
+{
+  struct c_binding *b = NULL;
+  tree name = TYPE_NAME (type);
+
+  if (name)
+    b = I_TAG_BINDING (name);
+
+  if (b)
+    b = b->shadowed;
+
+  if (b && B_IN_CURRENT_SCOPE (b))
+    return b->decl;
+
+  return NULL_TREE;
+}
+
 /* Subroutine of duplicate_decls.  Compare NEWDECL to OLDDECL.
    Returns true if the caller should proceed to merge the two, false
    if OLDDECL should simply be discarded.  As a side effect, issues
@@ -8573,11 +8595,14 @@ get_parm_info (bool ellipsis, tree expr)
 	  if (TREE_CODE (decl) != UNION_TYPE || b->id != NULL_TREE)
 	    {
 	      if (b->id)
-		/* The %s will be one of 'struct', 'union', or 'enum'.  */
-		warning_at (b->locus, 0,
-			    "%<%s %E%> declared inside parameter list"
-			    " will not be visible outside of this definition or"
-			    " declaration", keyword, b->id);
+		{
+		  /* The %s will be one of 'struct', 'union', or 'enum'.  */
+		  if (!flag_isoc23)
+		    warning_at (b->locus, 0,
+				"%<%s %E%> declared inside parameter list"
+				" will not be visible outside of this definition or"
+				" declaration", keyword, b->id);
+		}
 	      else
 		/* The %s will be one of 'struct', 'union', or 'enum'.  */
 		warning_at (b->locus, 0,
@@ -8668,6 +8693,16 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name,
      present, only a definition in the current scope is relevant.  */
 
   ref = lookup_tag (code, name, has_enum_type_specifier, &refloc);
+
+  /* If the visble type is still being defined, see if there is
+     an earlier definition (which may be complete).  */
+  if (flag_isoc23 && ref && C_TYPE_BEING_DEFINED (ref))
+    {
+      tree vis = previous_tag (ref);
+      if (vis)
+	ref = vis;
+    }
+
   /* If this is the right type of tag, return what we found.
      (This reference will be shadowed by shadow_tag later if appropriate.)
      If this is the wrong type of tag, do not return it.  If it was the
@@ -8782,6 +8817,14 @@ start_struct (location_t loc, enum tree_code code, tree name,
 
   if (name != NULL_TREE)
     ref = lookup_tag (code, name, true, &refloc);
+
+  /* For C23, even if we already have a completed definition,
+     we do not use it. We will check for consistency later.
+     If we are in a nested redefinition the type is not
+     complete. We will then detect this below.  */
+  if (flag_isoc23 && ref && TYPE_SIZE (ref))
+    ref = NULL_TREE;
+
   if (ref && TREE_CODE (ref) == code)
     {
       if (TYPE_STUB_DECL (ref))
@@ -9576,6 +9619,25 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       warning_at (loc, 0, "union cannot be made transparent");
     }
 
+  /* Check for consistency with previous definition.  */
+  if (flag_isoc23)
+    {
+      tree vistype = previous_tag (t);
+      if (vistype
+	  && TREE_CODE (vistype) == TREE_CODE (t)
+	  && !C_TYPE_BEING_DEFINED (vistype))
+	{
+	  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);
+	  else if (!comptypes_same_p (t, vistype))
+	    error ("redefinition of struct or union %qT", t);
+	}
+    }
+
+  C_TYPE_BEING_DEFINED (t) = 0;
+
   tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t));
   for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
     {
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c6f38ec94a0..7df4d65bf7a 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -756,6 +756,7 @@ extern tree c_objc_common_truthvalue_conversion (location_t, tree);
 extern tree require_complete_type (location_t, tree);
 extern bool same_translation_unit_p (const_tree, const_tree);
 extern int comptypes (tree, tree);
+extern bool comptypes_same_p (tree, tree);
 extern int comptypes_check_different_types (tree, tree, bool *);
 extern int comptypes_check_enum_int (tree, tree, bool *);
 extern bool c_mark_addressable (tree, bool = false);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 1dbb4471a88..dc8a16df272 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1080,6 +1080,23 @@ comptypes (tree type1, tree type2)
   return ret ? (data.warning_needed ? 2 : 1) : 0;
 }
 
+
+/* Like comptypes, but it returns non-zero only for identical
+   types.  */
+
+bool
+comptypes_same_p (tree type1, tree type2)
+{
+  struct comptypes_data data = { };
+  bool ret = comptypes_internal (type1, type2, &data);
+
+  if (data.different_types_p)
+    return false;
+
+  return ret;
+}
+
+
 /* Like comptypes, but if it returns non-zero because enum and int are
    compatible, it sets *ENUM_AND_INT_P to true.  */
 
@@ -1266,11 +1283,11 @@ comptypes_internal (const_tree type1, const_tree type2,
     case ENUMERAL_TYPE:
     case RECORD_TYPE:
     case UNION_TYPE:
-      if (false)
-	{
-	  return tagged_types_tu_compatible_p (t1, t2, data);
-	}
-      return false;
+
+      if (!flag_isoc23)
+	return false;
+
+      return tagged_types_tu_compatible_p (t1, t2, data);
 
     case VECTOR_TYPE:
       return known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2))
@@ -7031,7 +7048,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   /* Aggregates in different TUs might need conversion.  */
   if ((codel == RECORD_TYPE || codel == UNION_TYPE)
       && codel == coder
-      && comptypes (type, rhstype))
+      && comptypes (TYPE_MAIN_VARIANT (type), TYPE_MAIN_VARIANT (rhstype)))
     return convert_and_check (expr_loc != UNKNOWN_LOCATION
 			      ? expr_loc : location, type, rhs);
 
@@ -8401,6 +8418,13 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
 	   conversion.  */
 	inside_init = convert (type, inside_init);
 
+      if ((code == RECORD_TYPE || code == UNION_TYPE)
+	  && !comptypes (TYPE_MAIN_VARIANT (type), TYPE_MAIN_VARIANT (TREE_TYPE (inside_init))))
+	{
+	  error_init (init_loc, "invalid initializer");
+	  return error_mark_node;
+	}
+
       if (require_constant
 	  && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
 	{
@@ -10486,7 +10510,7 @@ initialize_elementwise_p (tree type, tree value)
     return !VECTOR_TYPE_P (value_type);
 
   if (AGGREGATE_TYPE_P (type))
-    return type != TYPE_MAIN_VARIANT (value_type);
+    return !comptypes (type, TYPE_MAIN_VARIANT (value_type));
 
   return false;
 }
diff --git a/gcc/testsuite/gcc.dg/c23-enum-7.c b/gcc/testsuite/gcc.dg/c23-enum-7.c
index c9ef0882b41..ff8e145c2a8 100644
--- a/gcc/testsuite/gcc.dg/c23-enum-7.c
+++ b/gcc/testsuite/gcc.dg/c23-enum-7.c
@@ -26,17 +26,15 @@ enum e13 : short x13; /* { dg-error "'enum' underlying type may not be specified
 enum e14 : short f14 (); /* { dg-error "'enum' underlying type may not be specified here" } */
 typeof (enum e15 : long) x15; /* { dg-error "'enum' underlying type may not be specified here" } */
 int f16 (enum e16 : char p); /* { dg-error "'enum' underlying type may not be specified here" } */
-/* { dg-warning "will not be visible outside of this definition or declaration" "warning" { target *-*-* } .-1 } */
 int f17 (enum e17 : char); /* { dg-error "'enum' underlying type may not be specified here" } */
-/* { dg-warning "will not be visible outside of this definition or declaration" "warning" { target *-*-* } .-1 } */
 struct s18 { enum e18 : int x; }; /* { dg-error "'enum' underlying type may not be specified here" } */
 
 /* But those are OK if the enum content is defined.  */
 enum e19 : short { E19 } x19;
 enum e20 : long { E20 } f20 ();
 typeof (enum e21 : long { E21 }) x21;
-int f22 (enum e22 : long long { E22 } p); /* { dg-warning "will not be visible outside of this definition or
declaration" } */
-int f23 (enum e23 : long long { E23 } p); /* { dg-warning "will not be visible outside of this definition or
declaration" } */
+int f22 (enum e22 : long long { E22 } p);
+int f23 (enum e23 : long long { E23 } p);
 struct s24 { enum e24 : int { E24 } x; };
 
 /* Incompatible kinds of tags in the same scope are errors.  */
diff --git a/gcc/testsuite/gcc.dg/c23-tag-1.c b/gcc/testsuite/gcc.dg/c23-tag-1.c
new file mode 100644
index 00000000000..4a6207ec626
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-1.c
@@ -0,0 +1,67 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// allowed and forbidden redefinitions of the same struct/union in the same scope
+
+typedef struct p { int a; } pd_t;
+typedef struct p { int a; } pd_t;
+
+typedef struct bar { int x; } X;
+typedef struct bar { float x; } Y; /* { dg-error "redefinition of struct or union" } */
+
+void test(void)
+{
+	struct foo { int x; };
+	struct foo { float x; }; /* { dg-error "redefinition of struct or union" } */
+}
+
+struct aa { int a; };
+
+void f(void)
+{
+	typedef struct aa A;
+	struct bb { struct aa a; } x;
+	struct aa { int a; };
+	typedef struct aa A;		/* { dg-error "redefinition" } */
+	struct bb { struct aa a; } y; /* { dg-error "redefinition of struct or union" } */
+	(void)x; (void)y;
+}
+
+
+
+void h(void)
+{
+	struct a2 { int a; };
+	{
+		typedef struct a2 A;
+		struct b2 { struct a2 a; } x;
+		struct a2 { int a; };
+		typedef struct a2 A;		/* { dg-error "redefinition" } */
+		struct b2 { struct a2 a; } y; /* { dg-error "redefinition of struct or union" } */
+		(void)x; (void)y;
+	}
+}
+
+
+union cc { int x; float y; } z;
+union cc { int x; float y; } z1;
+union cc { float y; int x; } z2;	/* { dg-error "redefinition of struct or union" } */
+
+void g(void)
+{
+	struct s { int a; };
+	struct s { int a; } x0;
+	struct p { struct s c; } y1 = { x0 };
+	struct p { struct s { int a; } c; } y = { x0 };
+}
+
+struct q { struct { int a; }; }; 
+struct q { struct { int a; }; }; 
+struct q { int a; };  /* { dg-error "redefinition of struct or union" } */
+
+struct r { int a; char b[]; };
+struct r { int a; char b[]; };
+struct r { int a; char b[1]; }; /* { dg-error "redefinition of struct or union" } */
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-2.c b/gcc/testsuite/gcc.dg/c23-tag-2.c
new file mode 100644
index 00000000000..5dd4a21e9df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-2.c
@@ -0,0 +1,43 @@
+/* { dg-do compile { target { ! "*-*-*" } } }
+ * { dg-options "-std=c23" }
+ */
+
+// compatibility of structs in assignment
+
+typedef struct p { int a; } pd_t;
+
+void test1(void)
+{
+  pd_t y0;
+  struct p { int a; } x;
+  y0 = x;
+}
+
+void test2(void)
+{
+  struct p { int a; } x;
+  struct p y0 = x;
+}
+
+void test3(void)
+{
+  struct p { int a; } x;
+  pd_t y0 = x;
+}
+
+typedef struct p { int a; } p2_t;
+
+void test4(void)
+{
+  p2_t x;
+  pd_t y0 = x;
+}
+
+void test5(void)
+{
+  struct q { int a; } a;
+  struct q { int a; } b;
+  a = b;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-3.c b/gcc/testsuite/gcc.dg/c23-tag-3.c
new file mode 100644
index 00000000000..4847e783c82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-3.c
@@ -0,0 +1,16 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// conflicting types via linkage
+
+extern struct foo { int x; } x;
+extern struct bar { float x; } y;
+
+void test(void)
+{
+  extern struct foo { int x; } x;
+  extern struct bar { int x; } y;	/* { dg-error "conflicting types" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-4.c b/gcc/testsuite/gcc.dg/c23-tag-4.c
new file mode 100644
index 00000000000..8083c43f607
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-4.c
@@ -0,0 +1,26 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// conflicting types for anonymous structs / unions
+
+extern struct { int x; } a;
+extern struct { int x; } a;	/* { dg-error "conflicting types" } */
+
+extern union { int x; } b;
+extern union { int x; } b;	/* { dg-error "conflicting types" } */
+
+typedef struct { int x; } u;
+typedef struct { int x; } v;
+
+u c;
+v c;				/* { dg-error "conflicting types" } */
+
+typedef union { int x; } q;
+typedef union { int x; } r;
+
+q d;
+r d;				/* { dg-error "conflicting types" } */
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-5.c b/gcc/testsuite/gcc.dg/c23-tag-5.c
new file mode 100644
index 00000000000..ff40d07aef1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-5.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { ! "*-*-*" } } }
+ * { dg-options "-std=c23" }
+ */
+
+// nesting and parameters
+
+#define product_type(T, A, B) \
+struct product_ ## T { A a ; B b ; }
+#define sum_type(T, A, B) \
+struct sum_ ## T { _Bool flag ; union { A a ; B b ; }; }
+
+float foo1(product_type(iSfd_, int, sum_type(fd, float, double)) x)
+{
+	return x.b.a;
+}
+
+static void test1(void)
+{
+	product_type(iSfd_, int, sum_type(fd, float, double)) y = { 3, { 1, { .a = 1. } } };
+	product_type(iSfd_, int, sum_type(fd, float, double)) z = y;
+	product_type(iSfd_, int, sum_type(fd, float, double)) *zp = &y;
+	float a = foo1(y);
+	product_type(iSid_, int, sum_type(id, int, double)) *wp = &y; /* { dg-warning "incompatible pointer type" } */
+	float b = foo1(y);
+	product_type(iSid_, int, sum_type(id, int, double)) w = *wp;
+	(void)a; (void)b; (void)z; (void)zp; (void)w; (void)wp;
+}
+
+int main()
+{
+	test1();
+}
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-6.c b/gcc/testsuite/gcc.dg/c23-tag-6.c
new file mode 100644
index 00000000000..1b65ed3e35d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-6.c
@@ -0,0 +1,58 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// (in-)completeness
+
+struct foo {
+	char x[10];
+} x;
+
+// complete, same type
+
+struct foo {
+	_Static_assert(_Generic(&x, struct foo*: 1, default: 0));
+	char x[_Generic(&x, struct foo*: 10, default: 1)];
+	_Static_assert(_Generic(0, struct foo: 0, default: 1));
+};
+
+// incomplete, same type
+
+struct bar* p;
+struct bar {
+	_Static_assert(_Generic(p, struct bar*: 1, default: 0));
+	char x[_Generic(p, struct bar*: 10, default: 1)];
+	_Static_assert(_Generic(0, struct bar: 0, default: 1));	/* { dg-error "incomplete type" } */
+};
+
+struct bar {
+	char x[10];
+};
+
+struct h *hp;
+
+void f(void)
+{
+	// again incomplete, different type
+
+	struct foo { 
+		char x[_Generic(&x, struct foo*: 1, default: 10)]; 
+		_Static_assert(_Generic(0, struct foo: 0, default: 1));	/* { dg-error "incomplete type" } */
+	};
+
+	struct foo z;
+	_Static_assert(10 == sizeof(z.x), "");
+
+	// still incomplete, different type
+
+	struct h { 
+		char x[_Generic(hp, struct h*: 1, default: 10)]; 
+		_Static_assert(_Generic(0, struct h: 0, default: 1));	/* { dg-error "incomplete type" } */
+	};
+
+	struct h y;
+	_Static_assert(10 == sizeof(y.x), "");
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-7.c b/gcc/testsuite/gcc.dg/c23-tag-7.c
new file mode 100644
index 00000000000..dd3b5988e24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-7.c
@@ -0,0 +1,12 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=c23" }
+ */
+
+// recursive declarations
+
+extern struct bar { struct bar* p; int x; } b;
+extern struct bar { struct bar* p; int x; } b;
+
+struct foo { struct foo { struct foo* p; int x; }* p; int x; } a;	/* { dg-error "nested" } */
+
diff --git a/gcc/testsuite/gcc.dg/c23-tag-8.c b/gcc/testsuite/gcc.dg/c23-tag-8.c
new file mode 100644
index 00000000000..8b3b5ef5dfe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c23-tag-8.c
@@ -0,0 +1,10 @@
+/* { dg-do compile }
+   { dg-options "-std=c23" } */
+
+void foo(void)
+{
+	struct bar { struct bar* next; };
+	struct bar { struct bar* next; };
+	struct bar { struct bar { struct bar* next; }* next; };	/* { dg-error "nested" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-1.c b/gcc/testsuite/gcc.dg/gnu23-tag-1.c
new file mode 100644
index 00000000000..3c0303d4c3f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-1.c
@@ -0,0 +1,10 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=gnu23" }
+ */
+
+struct r { int a; char b[]; };
+struct r { int a; char b[0]; };	/* allowed GNU extension */
+struct r { int a; char b[1]; }; /* { dg-error "redefinition of struct or union" } */
+
+
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-2.c b/gcc/testsuite/gcc.dg/gnu23-tag-2.c
new file mode 100644
index 00000000000..73725c79ebf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-2.c
@@ -0,0 +1,19 @@
+/*
+ * { dg-do compile }
+ * { dg-options "-std=gnu23" }
+ */
+
+// conflicting attributes
+
+extern struct __attribute__(( transaction_safe )) foo { int x; } x;
+extern struct __attribute__(( unused )) foo2 { int x; } x2;
+extern struct __attribute__(( may_alias )) foo3 { int x; } x3;
+
+void test(void)
+{
+  extern struct foo { int x; } x;		/* { dg-error "conflicting types" } */
+  extern struct  foo2 { int x; } x2;
+  extern struct  foo3 { int x; } x3;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-3.c b/gcc/testsuite/gcc.dg/gnu23-tag-3.c
new file mode 100644
index 00000000000..8919144ef3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-3.c
@@ -0,0 +1,28 @@
+/* 
+ * { dg-do compile } 
+ * { dg-options "-Wno-vla -std=gnu23" } 
+ */
+
+// arrays in structs
+
+void foo(int n, int m)
+{
+	struct f { int b; int a[n]; };
+	struct f { int b; int a[n]; };	/* { dg-error "redefinition of struct or union" } */
+	struct f { int b; int a[m]; };	/* { dg-error "redefinition of struct or union" } */
+	struct f { int b; int a[5]; };	/* { dg-error "redefinition of struct or union" } */
+	struct f { int b; int a[]; };	/* { dg-error "redefinition of struct or union" } */
+
+	struct g { int a[n]; int b; };
+	struct g { int a[n]; int b; };	/* { dg-error "redefinition of struct or union" } */
+	struct g { int a[m]; int b; };	/* { dg-error "redefinition of struct or union" } */
+	struct g { int a[4]; int b; };	/* { dg-error "redefinition of struct or union" } */
+
+	struct h { int (*a)[n]; int b; };
+	struct h { int (*a)[n]; int b; };	/* { dg-error "redefinition of struct or union" } */
+	struct h { int (*a)[m]; int b; };	/* { dg-error "redefinition of struct or union" } */
+	struct h { int (*a)[4]; int b; };	/* { dg-error "redefinition of struct or union" } */
+	struct h { int (*a)[]; int b; };	/* { dg-error "redefinition of struct or union" } */
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-4.c b/gcc/testsuite/gcc.dg/gnu23-tag-4.c
new file mode 100644
index 00000000000..8db81c7b87d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu23-tag-4.c
@@ -0,0 +1,31 @@
+/* { dg-do compile }
+ * { dg-options "-std=gnu23" } */
+
+// structs with variably modified types
+
+void bar(int n, int m)
+{
+	struct f { int b; int a[n]; } *x;
+	{ struct f { int b; int a[n]; } *x2 = x; }
+	{ struct f { int b; int a[m]; } *x2 = x; }
+	{ struct f { int b; int a[5]; } *x2 = x; }
+	{ struct f { int b; int a[0]; }  *x2 = x; }
+	{ struct f { int b; int a[]; }  *x2 = x; }
+
+	struct g { int a[n]; int b; } *y;
+	{ struct g { int a[n]; int b; } *y2 = y; }
+	{ struct g { int a[m]; int b; } *y2 = y; }
+	{ struct g { int a[4]; int b; } *y2 = y; }
+
+	struct h { int b; int a[5]; } *w;
+	{ struct h { int b; int a[5]; } *w2 = w; }
+	{ struct h { int b; int a[n]; } *w2 = w; }
+	{ struct h { int b; int a[m]; } *w2 = w; }
+
+	struct i { int b; int (*a)(int c[n]); } *u;
+	{ struct i { int b; int (*a)(int c[4]); } *u2 = u; }
+	{ struct i { int b; int (*a)(int c[]); } *u2 = u; }
+	{ struct i { int b; int (*a)(int c[*]); } *u2 = u; }
+}
+
+
-- 
2.39.2



  parent reply	other threads:[~2023-11-27 13:16 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-16 21:36 c23 type compatibility rules, v3 Martin Uecker
2023-11-16 21:38 ` [PATCH 1/4] c23: tag compatibility rules for struct and unions Martin Uecker
2023-11-23 23:17   ` Joseph Myers
2023-11-16 21:38 ` [PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-11-23 23:26   ` Joseph Myers
2023-11-16 21:39 ` [PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-11-23 23:47   ` Joseph Myers
2023-11-26 22:48     ` Martin Uecker
2023-11-27  7:46       ` Richard Biener
2023-11-28  1:00       ` Joseph Myers
2023-11-28  6:49         ` Martin Uecker
2023-11-28 10:47         ` Richard Biener
2023-11-28 11:51           ` Martin Uecker
2023-11-16 21:40 ` [PATCH 4/4] c23: construct composite type for " Martin Uecker
2023-11-27 13:16 ` Martin Uecker [this message]
2023-12-14 20:53   ` [V4] [C PATCH 1/4] c23: tag compatibility rules for struct and unions Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-12-14 20:58   ` Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-12-14 21:10   ` Joseph Myers
2023-11-27 13:16 ` [V4] [PATCH 4/4] c23: construct composite type for " Martin Uecker
2023-12-17 17:41 ` [V5] [C PATCH 1/4] c23: tag compatibility rules for struct and unions Martin Uecker
2023-12-19 21:48   ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 2/4] c23: tag compatibility rules for enums Martin Uecker
2023-12-19 21:50   ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 3/4] c23: aliasing of compatible tagged types Martin Uecker
2023-12-19 22:02   ` Joseph Myers
2023-12-17 17:42 ` [V5] [C PATCH 4/4] c23: construct composite type for " Martin Uecker
2023-12-19 22:25   ` Joseph Myers
2023-12-21 21:47 ` [V6] " Martin Uecker
2023-12-22 16:27   ` Joseph Myers
2023-12-27 19:23 ` [C PATCH] C: Fix type compatibility for structs with variable sized fields Martin Uecker
2023-12-29 15:57   ` Joseph Myers
2024-01-27 16:10 ` Fix ICE with -g and -std=c23 when forming composite types [PR113438] Martin Uecker
2024-01-29 20:27   ` Joseph Myers
2024-04-02 18:54 ` [C PATCH] Fix ICE with -g and -std=c23 related to incomplete types [PR114361] Martin Uecker
2024-04-02 20:31   ` Joseph Myers
2024-04-02 19:02 ` [C PATCH] fix aliasing for structures/unions with incomplete types Martin Uecker
2024-04-02 20:42   ` Joseph Myers
2024-04-02 21:22     ` Martin Uecker
2024-04-03 15:33       ` Joseph Myers
2024-04-14 12:30 ` [C PATCH, v2] Fix ICE with -g and -std=c23 related to incomplete types [PR114361] Martin Uecker
2024-04-14 12:38   ` Martin Uecker
2024-04-15  6:55   ` Richard Biener
2024-04-15  7:38     ` Jakub Jelinek
2024-04-15  7:59       ` Jakub Jelinek
2024-04-15  8:02         ` Richard Biener
2024-04-15  8:05           ` Jakub Jelinek
2024-04-15 10:48             ` [PATCH] c, v3: " Jakub Jelinek
2024-04-15 11:33               ` Richard Biener
2024-04-16  7:20                 ` Jakub Jelinek
2024-04-19 20:39               ` Joseph Myers
2024-04-15  7:03   ` [C PATCH, v2] " Jakub Jelinek
2024-05-18 13:27 ` [C PATCH] Fix for some variably modified types not being recognized [PR114831] Martin Uecker
2024-05-18 13:29   ` Martin Uecker
2024-05-20 21:18   ` Joseph Myers
2024-05-18 20:18 ` [C PATCH] Fix for redeclared enumerator initialized with different type [PR115109] Martin Uecker
2024-05-19 10:24   ` [C PATCH, v2] " Martin Uecker
2024-05-20 21:30     ` Joseph Myers
2024-05-21  5:40       ` Martin Uecker
2024-05-23 20:51         ` Joseph Myers
2024-05-21 12:18   ` [C PATCH]: allow aliasing of compatible types derived from enumeral types [PR115157] Martin Uecker
2024-05-23 20:59     ` Joseph Myers
2024-05-23 21:30       ` Ian Lance Taylor
2024-05-23 21:47         ` Martin Uecker
2024-05-23 21:53           ` Ian Lance Taylor
2024-05-24  5:56             ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=85008511e64113eaf86afa8b546ed55fd3620177.camel@tugraz.at \
    --to=uecker@tugraz.at \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).