Implement C11 DR#423 resolution (ignore function return type qualifiers).
authorJoseph Myers <joseph@codesourcery.com>
Fri, 13 May 2016 21:35:39 +0000 (22:35 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Fri, 13 May 2016 21:35:39 +0000 (22:35 +0100)
The resolution of C11 DR#423, apart from doing things with the types
of expressions cast to qualified types which are only in standard
terms observable with _Generic and which agree with how GCC has
implemented _Generic all along, also specifies that qualifiers are
discarded from function return types: "derived-declarator-type-list
function returning T" becomes "derived-declarator-type-list function
returning the unqualified version of T" in the rules giving types for
function declarators.  This means that declarations of a function with
both qualified and unqualified return types are now compatible,
similar to how different declarations can vary in whether a function
argument is declared with a qualifier or unqualified type.

This patch implements this resolution.  Since the motivation for the
change was _Generic, the resolution is restricted to C11 mode; there's
no reason to consider there to be a defect in this regard in older
standard versions.  Some less-obvious issues are handled as follows:

* As usual, and as with function arguments, _Atomic is not considered
  a qualifier for this purpose; that is, function declarations must
  agree regarding whether the return type is atomic.

* By 6.9.1#2, a function definition cannot return qualified void.  But
  with this change, specifying "const void" in the declaration
  produces the type "function returning void", which is perfectly
  valid, so "const void f (void) {}" is no longer an error.

* The application to restrict is less clear.  The way I am
  interpreting it in this patch is that "unqualified version of T" is
  not valid if T is not valid, as in the case where T is a
  restrict-qualified version of a type that cannot be restrict
  qualified (non-pointer, or pointer-to-function).  But it's possible
  to argue the other way from the wording.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

gcc/c:
* c-decl.c (grokdeclarator): For C11, discard qualifiers on
function return type.

gcc/testsuite:
* gcc.dg/qual-return-5.c, gcc.dg/qual-return-6.c: New tests.
* gcc.dg/call-diag-2.c, gcc.dg/qual-return-2.c ,
gcc.dg/qual-return-3.c, gcc.dg/qual-return-4.c: Use -std=gnu99.

From-SVN: r236231

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/call-diag-2.c
gcc/testsuite/gcc.dg/qual-return-2.c
gcc/testsuite/gcc.dg/qual-return-3.c
gcc/testsuite/gcc.dg/qual-return-4.c
gcc/testsuite/gcc.dg/qual-return-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/qual-return-6.c [new file with mode: 0644]

index af0bbe4bef5662ae79cd0023f8e5df80442a439b..c726e9fde17ba5fd05b38bd548e4dc9a13c8c08b 100644 (file)
@@ -1,3 +1,8 @@
+2016-05-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * c-decl.c (grokdeclarator): For C11, discard qualifiers on
+       function return type.
+
 2016-05-12  Marek Polacek  <polacek@redhat.com>
 
        PR c/70756
index 19260343c553416131d607b7692cff6b64fb220f..b2dd644748ed52501b17d1fbab92bb0ff1917dd8 100644 (file)
@@ -6106,20 +6106,35 @@ grokdeclarator (const struct c_declarator *declarator,
               qualify the return type, not the function type.  */
            if (type_quals)
              {
+               int quals_used = type_quals;
                /* Type qualifiers on a function return type are
                   normally permitted by the standard but have no
                   effect, so give a warning at -Wreturn-type.
                   Qualifiers on a void return type are banned on
                   function definitions in ISO C; GCC used to used
-                  them for noreturn functions.  */
-               if (VOID_TYPE_P (type) && really_funcdef)
+                  them for noreturn functions.  The resolution of C11
+                  DR#423 means qualifiers (other than _Atomic) are
+                  actually removed from the return type when
+                  determining the function type.  */
+               if (flag_isoc11)
+                 quals_used &= TYPE_QUAL_ATOMIC;
+               if (quals_used && VOID_TYPE_P (type) && really_funcdef)
                  pedwarn (loc, 0,
                           "function definition has qualified void return type");
                else
                  warning_at (loc, OPT_Wignored_qualifiers,
                           "type qualifiers ignored on function return type");
 
-               type = c_build_qualified_type (type, type_quals);
+               /* Ensure an error for restrict on invalid types; the
+                  DR#423 resolution is not entirely clear about
+                  this.  */
+               if (flag_isoc11
+                   && (type_quals & TYPE_QUAL_RESTRICT)
+                   && (!POINTER_TYPE_P (type)
+                       || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+                 error_at (loc, "invalid use of %<restrict%>");
+               if (quals_used)
+                 type = c_build_qualified_type (type, quals_used);
              }
            type_quals = TYPE_UNQUALIFIED;
 
index 7ef07977cef46e01fd31dbc365d9c92d747fa251..9a8cd750ea624758bbcab5b06123adc9b6a5f675 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * gcc.dg/qual-return-5.c, gcc.dg/qual-return-6.c: New tests.
+       * gcc.dg/call-diag-2.c, gcc.dg/qual-return-2.c ,
+       gcc.dg/qual-return-3.c, gcc.dg/qual-return-4.c: Use -std=gnu99.
+
 2016-05-13  Martin Sebor  <msebor@redhat.com>
 
        PR c++/60049
index c34252cd7294998dd60159ddc3cddb74cf219754..b998ea9d76043b7e18788fe1732943ba380e3802 100644 (file)
@@ -1,7 +1,7 @@
 /* Test diagnostics for calling function returning qualified void or
    other incomplete type other than void.  PR 35210.  */
 /* { dg-do compile } */
-/* { dg-options "-pedantic-errors" } */
+/* { dg-options "-std=gnu99 -pedantic-errors" } */
 
 const void f_cv (void);
 struct s f_s (void);
index 22a1946b03fe477e67ed6e409f48a735cb974c92..1cd1253518bfb870786cf7571b00ebc536ef86c4 100644 (file)
@@ -1,7 +1,7 @@
 /* Test for warnings for qualified function return types.  -pedantic test.  */
 /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
 /* { dg-do compile } */
-/* { dg-options "-pedantic" } */
+/* { dg-options "-pedantic -std=gnu99" } */
 
 /* Qualifying a function return type makes no sense.  */
 
index e65f86d547d42e986d8c8bac30e91566f28b251f..bd760799d98e26b7c6bb6eda57d5b9d85652493c 100644 (file)
@@ -4,7 +4,7 @@
 
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-std=gnu99" } */
 
 int foo (); /* { dg-message "note: previous declaration" "different qualifiers" } */
 const int foo () { return 0; } /* { dg-error "conflicting types" "different qualifiers" } */
index 9b61cfebf126f4532a2516f25bd4727753361e65..7bb5b6919733159cf994380817c28e3dda6f74e7 100644 (file)
@@ -3,7 +3,7 @@
    types, not other such types within the definition.  */
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
-/* { dg-options "-pedantic" } */
+/* { dg-options "-pedantic -std=gnu99" } */
 
 volatile void (*y)(int);
 
diff --git a/gcc/testsuite/gcc.dg/qual-return-5.c b/gcc/testsuite/gcc.dg/qual-return-5.c
new file mode 100644 (file)
index 0000000..32a08f2
--- /dev/null
@@ -0,0 +1,32 @@
+/* Test qualifiers on function return types after DR#423: those
+   qualifiers are now ignored for all purposes (but _Atomic is not,
+   for this purpose, a qualifier).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int f1 (void);
+const int f1 (void);
+volatile int f1 (void) { return 0; }
+
+int *restrict f2 (void) { return 0; }
+int *f2 (void);
+
+const volatile long f3 (void);
+long f3 (void);
+
+const volatile void f4 (void) { }
+void f4 (void);
+
+_Atomic int f5 (void); /* { dg-message "previous declaration" } */
+int f5 (void); /* { dg-error "conflicting" } */
+
+int f6 (void); /* { dg-message "previous declaration" } */
+_Atomic int f6 (void) { return 0; } /* { dg-error "conflicting" } */
+
+/* The standard seems unclear regarding the case where restrict is
+   applied to a function return type that may not be
+   restrict-qualified; assume here that it is disallowed.  */
+restrict int f7 (void); /* { dg-error "restrict" } */
+
+typedef void FT (void);
+FT *restrict f8 (void); /* { dg-error "restrict" } */
diff --git a/gcc/testsuite/gcc.dg/qual-return-6.c b/gcc/testsuite/gcc.dg/qual-return-6.c
new file mode 100644 (file)
index 0000000..5b3ded0
--- /dev/null
@@ -0,0 +1,12 @@
+/* Test qualifiers on function return types after DR#423: those
+   qualifiers are now ignored for all purposes (except that _Atomic
+   still affects the type), but should still get warnings.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -Wignored-qualifiers" } */
+
+const int f1 (void); /* { dg-warning "qualifiers ignored" } */
+volatile int f2 (void) { return 0; } /* { dg-warning "qualifiers ignored" } */
+const volatile void f3 (void) { } /* { dg-warning "qualifiers ignored" } */
+const void f4 (void); /* { dg-warning "qualifiers ignored" } */
+_Atomic int f5 (void); /* { dg-warning "qualifiers ignored" } */
+_Atomic int f6 (void) { return 0; } /* { dg-warning "qualifiers ignored" } */