C2Y removes various instances of undefined behavior, typically making
them either constraint violations or implementation-defined.

In many but not all such cases, GCC's existing behavior is compatible
with the C2Y changes.  For an initial batch of such cases, add
explicit tests for how GCC behaves in C2Y mode; more such cases will
need tests added in future patches, and there are also some such
changes that will need changes to how GCC behaves, not just new tests.
(Some of the individual examples in these tests may have been
constraint violations even before C2Y.)

Tested for x86_64-pc-linux-gnu.

        * gcc.dg/c2y-function-qual-1.c, gcc.dg/c2y-incomplete-1.c,
        gcc.dg/c2y-inline-1.c, gcc.dg/c2y-pointer-1.c,
        gcc.dg/c2y-register-array-1.c, gcc.dg/c2y-storage-class-1.c,
        gcc.dg/c2y-struct-empty-1.c: New tests.

diff --git a/gcc/testsuite/gcc.dg/c2y-function-qual-1.c 
b/gcc/testsuite/gcc.dg/c2y-function-qual-1.c
new file mode 100644
index 000000000000..eef8d8af7b37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-function-qual-1.c
@@ -0,0 +1,13 @@
+/* Test qualified function types: implementation-defined in C2y, undefined
+   behavior previously.  GCC has an extension here, but does not allow it in
+   pedantic mode.  _Atomic and restrict are constraint violations here.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+typedef void FUNC (void);
+
+const FUNC f1; /* { dg-error "ISO C forbids qualified function types" } */
+volatile FUNC f2; /* { dg-error "ISO C forbids qualified function types" } */
+restrict FUNC f3; /* { dg-error "ISO C forbids qualified function types" } */
+/* { dg-error "invalid use of 'restrict'" "restrict" { target *-*-* } .-1 } */
+_Atomic FUNC f4; /* { dg-error "'_Atomic'-qualified function type" } */
diff --git a/gcc/testsuite/gcc.dg/c2y-incomplete-1.c 
b/gcc/testsuite/gcc.dg/c2y-incomplete-1.c
new file mode 100644
index 000000000000..2d7b1812ac2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-incomplete-1.c
@@ -0,0 +1,20 @@
+/* Test C2y constraint for incomplete types of objects with no linkage.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+struct s1;
+
+void
+f ()
+{
+  struct s1 a; /* { dg-error "storage size" } */
+  int b[]; /* { dg-error "array size missing" } */
+  static struct s1 c; /* { dg-error "storage size" } */
+  static int d[]; /* { dg-error "array size missing" } */
+  struct s2;
+  struct s2 e; /* { dg-error "storage size" } */
+  static struct s2 g; /* { dg-error "storage size" } */
+  struct s2 { int i; };
+}
+
+struct s1 { int j; };
diff --git a/gcc/testsuite/gcc.dg/c2y-inline-1.c 
b/gcc/testsuite/gcc.dg/c2y-inline-1.c
new file mode 100644
index 000000000000..b65fa5fc0826
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-inline-1.c
@@ -0,0 +1,7 @@
+/* Test C2y constraint that inline functions with external linkage must be
+   defined in same translation unit.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+inline void f (); /* { dg-error "declared but never defined" } */
+extern inline void g(); /* { dg-error "declared but never defined" } */
diff --git a/gcc/testsuite/gcc.dg/c2y-pointer-1.c 
b/gcc/testsuite/gcc.dg/c2y-pointer-1.c
new file mode 100644
index 000000000000..04d59dd200e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-pointer-1.c
@@ -0,0 +1,53 @@
+/* Test C2y constraints on pointer conversions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+#include <stddef.h>
+#include <stdint.h>
+
+void *p1;
+struct s { int a; } s1;
+struct sp { void *p; } s2;
+union t { int b; } t1;
+union tp { void *p; } t2;
+
+void
+f ()
+{
+  (double) p1; /* { dg-error "pointer value used where a floating-point was 
expected" } */
+  (struct s) p1; /* { dg-error "conversion to non-scalar type requested" } */
+  (union t) p1; /* { dg-error "cast to union type from type not present in 
union" } */
+  (struct sp) p1; /* { dg-error "conversion to non-scalar type requested" } */
+  (union tp) p1; /* { dg-error "ISO C forbids casts to union type" } */
+  (nullptr_t) p1; /* { dg-error "conversion" } */
+  /* { dg-message "or a null pointer constant can be converted" "conversion 
note" { target *-*-* } .-1 } */
+  (intptr_t) p1;
+  (int *) p1;
+  (void) p1;
+  (void *) 0.0; /* { dg-error "cannot convert to a pointer type" } */
+  (void *) s1; /* { dg-error "cannot convert to a pointer type" } */
+  (void *) t1; /* { dg-error "cannot convert to a pointer type" } */
+  (void *) s2; /* { dg-error "cannot convert to a pointer type" } */
+  (void *) t2; /* { dg-error "cannot convert to a pointer type" } */
+  (void *) nullptr;
+  (void *) 0;
+  (void *) (int *) 0;
+  (void *) (void) p1; /* { dg-error "invalid use of void expression" } */
+}
+
+void
+g ()
+{
+  double d = p1; /* { dg-error "incompatible types" } */
+  s1 = p1; /* { dg-error "incompatible types" } */
+  t1 = p1; /* { dg-error "incompatible types" } */
+  s2 = p1; /* { dg-error "incompatible types" } */
+  t2 = p1; /* { dg-error "incompatible types" } */
+  nullptr_t np = p1; /* { dg-error "incompatible types" } */
+  p1 = 0.0; /* { dg-error "incompatible types" } */
+  p1 = s1; /* { dg-error "incompatible types" } */
+  p1 = t1; /* { dg-error "incompatible types" } */
+  p1 = s2; /* { dg-error "incompatible types" } */
+  p1 = t2; /* { dg-error "incompatible types" } */
+  p1 = (void) p1; /* { dg-error "invalid use of void expression" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-register-array-1.c 
b/gcc/testsuite/gcc.dg/c2y-register-array-1.c
new file mode 100644
index 000000000000..1744b3bc1274
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-register-array-1.c
@@ -0,0 +1,21 @@
+/* Test implicit conversion of register arrays to pointers:
+   implementation-defined in C2y, undefined behavior previously.  GCC disallows
+   this conversion (the case of array element access changed in C2y no longer
+   to involve the implicit conversion to a pointer).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+void
+f ()
+{
+  register int a[1];
+  constexpr register int b[1] = { 1 };
+  a; /* { dg-error "address of register variable" } */
+  b; /* { dg-error "address of register variable" } */
+  (void) a; /* { dg-error "address of register variable" } */
+  (void) b; /* { dg-error "address of register variable" } */
+  *a; /* { dg-error "address of register variable" } */
+  *b; /* { dg-error "address of register variable" } */
+  a + 0; /* { dg-error "address of register variable" } */
+  b + 0; /* { dg-error "address of register variable" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-storage-class-1.c 
b/gcc/testsuite/gcc.dg/c2y-storage-class-1.c
new file mode 100644
index 000000000000..af9c41caf50b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-storage-class-1.c
@@ -0,0 +1,18 @@
+/* Test C2y constraint on storage-class specifiers for block-scope identifiers
+   for functions.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+void
+f ()
+{
+  auto void g1 (); /* { dg-error "invalid storage class for function" } */
+  /* { dg-error "nested function" "nested" { target *-*-* } .-1 } */
+  constexpr void g2 (); /* { dg-error "requires an initialized data 
declaration" } */
+  extern void g3 ();
+  register void g4 (); /* { dg-error "invalid storage class for function" } */
+  static void g5 (); /* { dg-error "invalid storage class for function" } */
+  thread_local void g6 (); /* { dg-error "implicitly auto and declared" } */
+  static thread_local void g7 (); /* { dg-error "invalid storage class for 
function" } */
+  /* { dg-error "nested function" "nested" { target *-*-* } .-1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/c2y-struct-empty-1.c 
b/gcc/testsuite/gcc.dg/c2y-struct-empty-1.c
new file mode 100644
index 000000000000..b6361685a757
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2y-struct-empty-1.c
@@ -0,0 +1,10 @@
+/* Test structures and unions without named members: implementation-defined in
+   C2y, undefined behavior previously.  GCC has an extension here, but does not
+   allow it in pedantic mode.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c2y -pedantic-errors" } */
+
+struct s1 { }; /* { dg-error "struct has no members" } */
+union u1 { }; /* { dg-error "union has no members" } */
+struct s2 { struct { }; }; /* { dg-error "struct has no members" } */
+struct s3 { int : 3; int : 4; }; /* { dg-error "struct has no named members" } 
*/

-- 
Joseph S. Myers
josmy...@redhat.com

Reply via email to