Commit aa4b467b by Joseph Myers Committed by Joseph Myers

Implement C11 DR#423 resolution (ignore function return type qualifiers).

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
parent 653fb4a2
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> 2016-05-12 Marek Polacek <polacek@redhat.com>
PR c/70756 PR c/70756
......
...@@ -6106,20 +6106,35 @@ grokdeclarator (const struct c_declarator *declarator, ...@@ -6106,20 +6106,35 @@ grokdeclarator (const struct c_declarator *declarator,
qualify the return type, not the function type. */ qualify the return type, not the function type. */
if (type_quals) if (type_quals)
{ {
int quals_used = type_quals;
/* Type qualifiers on a function return type are /* Type qualifiers on a function return type are
normally permitted by the standard but have no normally permitted by the standard but have no
effect, so give a warning at -Wreturn-type. effect, so give a warning at -Wreturn-type.
Qualifiers on a void return type are banned on Qualifiers on a void return type are banned on
function definitions in ISO C; GCC used to used function definitions in ISO C; GCC used to used
them for noreturn functions. */ them for noreturn functions. The resolution of C11
if (VOID_TYPE_P (type) && really_funcdef) 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, pedwarn (loc, 0,
"function definition has qualified void return type"); "function definition has qualified void return type");
else else
warning_at (loc, OPT_Wignored_qualifiers, warning_at (loc, OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type"); "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; type_quals = TYPE_UNQUALIFIED;
......
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> 2016-05-13 Martin Sebor <msebor@redhat.com>
PR c++/60049 PR c++/60049
......
/* Test diagnostics for calling function returning qualified void or /* Test diagnostics for calling function returning qualified void or
other incomplete type other than void. PR 35210. */ other incomplete type other than void. PR 35210. */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-pedantic-errors" } */ /* { dg-options "-std=gnu99 -pedantic-errors" } */
const void f_cv (void); const void f_cv (void);
struct s f_s (void); struct s f_s (void);
......
/* Test for warnings for qualified function return types. -pedantic test. */ /* Test for warnings for qualified function return types. -pedantic test. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */ /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-pedantic" } */ /* { dg-options "-pedantic -std=gnu99" } */
/* Qualifying a function return type makes no sense. */ /* Qualifying a function return type makes no sense. */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "" } */ /* { dg-options "-std=gnu99" } */
int foo (); /* { dg-message "note: previous declaration" "different qualifiers" } */ int foo (); /* { dg-message "note: previous declaration" "different qualifiers" } */
const int foo () { return 0; } /* { dg-error "conflicting types" "different qualifiers" } */ const int foo () { return 0; } /* { dg-error "conflicting types" "different qualifiers" } */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
types, not other such types within the definition. */ types, not other such types within the definition. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */ /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-pedantic" } */ /* { dg-options "-pedantic -std=gnu99" } */
volatile void (*y)(int); volatile void (*y)(int);
......
/* 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" } */
/* 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" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment