C90 conformance: return statements without expressions in non-void functions

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

C90 conformance: return statements without expressions in non-void functions

Ken Dyck
I have been using the Plum Hall Validation Suite for C [1] to validate a
Clang/LLVM backend that I'm working on.

In the conformance-testing code of the suite is defined the following
function:

  // test2.c
  int iequals(int, int, int);
 
  #if !defined(CPLUSPLUS) && !defined(C99)
  yfunc(i, pfn, pi) /* no return type, default to int */
    int i;
    int pfn();  /* parm w fn type becomes ptr-to-fn */
    int *pi;
  #else
  int yfunc(int i, int pfn(int*), int* pi) /* make yfunc explicit int
for C++ */
      /* parm w fn type becomes ptr-to-fn */
  #endif /* CPLUSPLUS */
  {
    static int j = 3;

    iequals(__LINE__, i, j);
    if (--i == 0)
  #if !defined(CPLUSPLUS) && !defined(C99)
      return;
  #else
      return 0;
  #endif
    --j;
    yfunc(i, pfn, pi);
    iequals(__LINE__, i, j);
    ++j;
    pfn(pi);  /* converts to (*pfn)() */
  #if !defined(CPLUSPLUS) && !defined(C99)
    /* no return expression, would be erroneous to use value */
  #else
    return 0; /* must return expr, in C++ */
  #endif /* CPLUSPLUS */
  }

The C99 macro is defined when testing against the C99 standard and is
undefined for C90.

This code fails to compile with Clang in the C90 case:

  > clang -S -x c -std=iso9899:1990 -o - test2.c
  test2.c:19:5: error: non-void function 'yfunc' should return a value
        [-Wreturn-type]
      return;
      ^
  1 error generated.

Section 6.6.4 of C90 reads, "If a return statement without an expression
is executed, and the value of the function call is used by the caller,
the behavior is undefined." The standard says nothing (at least that
I've found) about the case where the value of the function is _not_
used, which happens to be the case for yfunc() in the context of the
validation suite.

Can any language lawyers comment on whether yfunc() should compile in
C90 mode?

-Ken

[1] http://www.plumhall.com/stec.html

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

Douglas Gregor

On Sep 14, 2010, at 7:54 AM, Ken Dyck wrote:

> I have been using the Plum Hall Validation Suite for C [1] to validate a
> Clang/LLVM backend that I'm working on.
>
> In the conformance-testing code of the suite is defined the following
> function:
> [snip]
> The C99 macro is defined when testing against the C99 standard and is
> undefined for C90.
>
> This code fails to compile with Clang in the C90 case:
>
>> clang -S -x c -std=iso9899:1990 -o - test2.c
>  test2.c:19:5: error: non-void function 'yfunc' should return a value
>        [-Wreturn-type]
>      return;
>      ^
>  1 error generated.
>
> Section 6.6.4 of C90 reads, "If a return statement without an expression
> is executed, and the value of the function call is used by the caller,
> the behavior is undefined." The standard says nothing (at least that
> I've found) about the case where the value of the function is _not_
> used, which happens to be the case for yfunc() in the context of the
> validation suite.
>
> Can any language lawyers comment on whether yfunc() should compile in
> C90 mode?


I don't know the C90 standard well, but from the statement you quote it seems that Clang is non-conformant.

That said, from a user's perspective, Clang is doing the right thing: writing a "return" statement with no expression, in a function that has a non-void return type, is asking for trouble, and we're doing users a favor by rejecting it outright. Plum Hall isn't helping anyone by checking this.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

Chris Lattner
On Sep 14, 2010, at 8:39 AM, Douglas Gregor wrote:

>> The C99 macro is defined when testing against the C99 standard and is
>> undefined for C90.
>>
>> This code fails to compile with Clang in the C90 case:
>>
>>> clang -S -x c -std=iso9899:1990 -o - test2.c
>> test2.c:19:5: error: non-void function 'yfunc' should return a value
>>       [-Wreturn-type]
>>     return;
>>     ^
>> 1 error generated.
>>
>> Section 6.6.4 of C90 reads, "If a return statement without an expression
>> is executed, and the value of the function call is used by the caller,
>> the behavior is undefined." The standard says nothing (at least that
>> I've found) about the case where the value of the function is _not_
>> used, which happens to be the case for yfunc() in the context of the
>> validation suite.
>>
>> Can any language lawyers comment on whether yfunc() should compile in
>> C90 mode?
>
>
> I don't know the C90 standard well, but from the statement you quote it seems that Clang is non-conformant.
>
> That said, from a user's perspective, Clang is doing the right thing: writing a "return" statement with no expression, in a function that has a non-void return type, is asking for trouble, and we're doing users a favor by rejecting it outright. Plum Hall isn't helping anyone by checking this.

We're doing the right thing here.  That error is actually a warning that is mapped to an error.  If you want full c90 conformance, you should pass -Wno-return-type or -Wreturn-type.  However, I could be convinced that the default mapping in -std=c89 mode (but not -std=gnu89 mode) should be to warning.  If you're interested, please prepare a patch for that.  Thanks Ken,

-Chris
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

Ken Dyck


On Tuesday, September 14, 2010 12:01 PM, Chris Lattner

>
> On Sep 14, 2010, at 8:39 AM, Douglas Gregor
> wrote:
> >> The C99 macro is defined when testing
> against the C99 standard and is
> >> undefined for C90.
> >>
> >> This code fails to compile with Clang in
> the C90 case:
> >>
> >>> clang -S -x c -std=iso9899:1990 -o -
> test2.c
> >> test2.c:19:5: error: non-void function
> 'yfunc' should return a value
> >>       [-Wreturn-type]
> >>     return;
> >>     ^
> >> 1 error generated.
> >>
> >> Section 6.6.4 of C90 reads, "If a return
> statement without an expression
> >> is executed, and the value of the function
> call is used by the caller,
> >> the behavior is undefined." The standard
> says nothing (at least that
> >> I've found) about the case where the value
> of the function is _not_
> >> used, which happens to be the case for
> yfunc() in the context of the
> >> validation suite.
> >>
> >> Can any language lawyers comment on
> whether yfunc() should compile in
> >> C90 mode?
> >
> >
> > I don't know the C90 standard well, but
> from the statement you quote it seems that
> Clang is non-conformant.
> >
> > That said, from a user's perspective, Clang
> is doing the right thing: writing a "return"
> statement with no expression, in a function
> that has a non-void return type, is asking
> for trouble, and we're doing users a favor by
> rejecting it outright. Plum Hall isn't
> helping anyone by checking this.
>
> We're doing the right thing here.  That error
> is actually a warning that is mapped to an
> error.  If you want full c90 conformance, you
> should pass -Wno-return-type or -Wreturn-
> type.  

That seems to disable more errors than are allowed by C90. The one
constraint C90 imposes in 6.6.6.4 is, "A return statement with an
expression shall not appear in a function whose return type is void."
With, -Wno-return-type or -Wreturn-type, Clang generates warnings
instead of errors for:

  void superfluous_return_expr(void)
  {
    return 0;
  }

> However, I could be convinced that the
> default mapping in -std=c89 mode (but not -
> std=gnu89 mode) should be to warning.  If
> you're interested, please prepare a patch for
> that.

I'm interested but might not get to it for a while. Shall I file a bug
in the meantime?

-Ken

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

Dale Johannesen
In reply to this post by Douglas Gregor

On Sep 14, 2010, at 8:39 AMPDT, Douglas Gregor wrote:
>>
>> Can any language lawyers comment on whether yfunc() should compile in
>> C90 mode?

 #if !defined(CPLUSPLUS) && !defined(C99)
 yfunc(i, pfn, pi) /* no return type, default to int */
   int i;
   int pfn();  /* parm w fn type becomes ptr-to-fn */
   int *pi;
 #else
 int yfunc(int i, int pfn(int*), int* pi) /* make yfunc explicit int
for C++ */
     /* parm w fn type becomes ptr-to-fn */
 #endif /* CPLUSPLUS */
 {
   static int j = 3;

   iequals(__LINE__, i, j);
   if (--i == 0)
 #if !defined(CPLUSPLUS) && !defined(C99)
     return;
 #else
     return 0;
 #endif
   --j;
   yfunc(i, pfn, pi);
   iequals(__LINE__, i, j);
   ++j;
   pfn(pi);  /* converts to (*pfn)() */
 #if !defined(CPLUSPLUS) && !defined(C99)
   /* no return expression, would be erroneous to use value */
 #else
   return 0; /* must return expr, in C++ */
 #endif /* CPLUSPLUS */
 }

> I don't know the C90 standard well, but from the statement you quote it seems that Clang is non-conformant.
>
> That said, from a user's perspective, Clang is doing the right thing: writing a "return" statement with no expression, in a function that has a non-void return type, is asking for trouble, and we're doing users a favor by rejecting it outright. Plum Hall isn't helping anyone by checking this.

As I read the test, the function is declared with no return type (i.e. implicit int).  This style was commonly used pre-C90 to declare functions that are logically void, as many compilers did not support void, and the C90 standard permits this usage in order to support such code.  How much of it is still around is an open question, probably not much, but I'm sure somebody stuck with maintaining such code would not consider it friendly to have the compiler reject it.


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

John McCall
On Sep 14, 2010, at 11:05 AM, Dale Johannesen wrote:

> On Sep 14, 2010, at 8:39 AMPDT, Douglas Gregor wrote:
>>>
>>> Can any language lawyers comment on whether yfunc() should compile in
>>> C90 mode?
>
> #if !defined(CPLUSPLUS) && !defined(C99)
> yfunc(i, pfn, pi) /* no return type, default to int */
>   int i;
>   int pfn();  /* parm w fn type becomes ptr-to-fn */
>   int *pi;
> #else
> int yfunc(int i, int pfn(int*), int* pi) /* make yfunc explicit int
> for C++ */
>     /* parm w fn type becomes ptr-to-fn */
> #endif /* CPLUSPLUS */
> {
>   static int j = 3;
>
>   iequals(__LINE__, i, j);
>   if (--i == 0)
> #if !defined(CPLUSPLUS) && !defined(C99)
>     return;
> #else
>     return 0;
> #endif
>   --j;
>   yfunc(i, pfn, pi);
>   iequals(__LINE__, i, j);
>   ++j;
>   pfn(pi);  /* converts to (*pfn)() */
> #if !defined(CPLUSPLUS) && !defined(C99)
>   /* no return expression, would be erroneous to use value */
> #else
>   return 0; /* must return expr, in C++ */
> #endif /* CPLUSPLUS */
> }
>
>> I don't know the C90 standard well, but from the statement you quote it seems that Clang is non-conformant.
>>
>> That said, from a user's perspective, Clang is doing the right thing: writing a "return" statement with no expression, in a function that has a non-void return type, is asking for trouble, and we're doing users a favor by rejecting it outright. Plum Hall isn't helping anyone by checking this.
>
> As I read the test, the function is declared with no return type (i.e. implicit int).  This style was commonly used pre-C90 to declare functions that are logically void, as many compilers did not support void, and the C90 standard permits this usage in order to support such code.  How much of it is still around is an open question, probably not much, but I'm sure somebody stuck with maintaining such code would not consider it friendly to have the compiler reject it.

This is a good point;  it would be totally reasonable for us to consider this a hard error unless the return type is implicit.

John.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: C90 conformance: return statements without expressions in non-void functions

Douglas Gregor

On Sep 14, 2010, at 11:41 AM, John McCall wrote:

> On Sep 14, 2010, at 11:05 AM, Dale Johannesen wrote:
>> On Sep 14, 2010, at 8:39 AMPDT, Douglas Gregor wrote:
>>>>
>>>> Can any language lawyers comment on whether yfunc() should compile in
>>>> C90 mode?
>>
>> #if !defined(CPLUSPLUS) && !defined(C99)
>> yfunc(i, pfn, pi) /* no return type, default to int */
>>  int i;
>>  int pfn();  /* parm w fn type becomes ptr-to-fn */
>>  int *pi;
>> #else
>> int yfunc(int i, int pfn(int*), int* pi) /* make yfunc explicit int
>> for C++ */
>>    /* parm w fn type becomes ptr-to-fn */
>> #endif /* CPLUSPLUS */
>> {
>>  static int j = 3;
>>
>>  iequals(__LINE__, i, j);
>>  if (--i == 0)
>> #if !defined(CPLUSPLUS) && !defined(C99)
>>    return;
>> #else
>>    return 0;
>> #endif
>>  --j;
>>  yfunc(i, pfn, pi);
>>  iequals(__LINE__, i, j);
>>  ++j;
>>  pfn(pi);  /* converts to (*pfn)() */
>> #if !defined(CPLUSPLUS) && !defined(C99)
>>  /* no return expression, would be erroneous to use value */
>> #else
>>  return 0; /* must return expr, in C++ */
>> #endif /* CPLUSPLUS */
>> }
>>
>>> I don't know the C90 standard well, but from the statement you quote it seems that Clang is non-conformant.
>>>
>>> That said, from a user's perspective, Clang is doing the right thing: writing a "return" statement with no expression, in a function that has a non-void return type, is asking for trouble, and we're doing users a favor by rejecting it outright. Plum Hall isn't helping anyone by checking this.
>>
>> As I read the test, the function is declared with no return type (i.e. implicit int).  This style was commonly used pre-C90 to declare functions that are logically void, as many compilers did not support void, and the C90 standard permits this usage in order to support such code.  How much of it is still around is an open question, probably not much, but I'm sure somebody stuck with maintaining such code would not consider it friendly to have the compiler reject it.
>
> This is a good point;  it would be totally reasonable for us to consider this a hard error unless the return type is implicit.

Yes, I agree.

        - Doug
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev