6

Using gcc 5.2.0, I noticed that this code does not generate a warning:

#include <stddef.h>

int function(void)
{
    return NULL;
}

void procedure(void)
{
    return NULL;
}

I used the flags -Wall -Wextra -std=c99 -pedantic and I am running archlinux. I am not sure why this code works fine on gcc, especially since clang 3.7.0 does generate a warning.

I also tried with older versions of gcc like 4.9 or 4.7 and they both generate warnings.

The warnings are:

warning: return makes integer from pointer without a cast

and

warning: ‘return’ with a value, in function returning void

I should mention that I tried compiling gcc 5.2 on Debian and the result is the same. So archlinux does not seem to be the problem.

What is the rationale? I cannot seem to find anything related to this anywhere else.

Thank you!

damwdan
  • 71
  • 5
  • 1
    possible duplicate http://stackoverflow.com/questions/1610030/why-can-you-return-from-a-non-void-function-without-returning-a-value-without-pr – asio_guy Sep 23 '15 at 06:16
  • Lol you mean "inverse duplicate"? This question asks why you can return a value in a body of a void function. The "duplicate" asks why you can write a body of a non-void function without a return statement. – BitTickler Sep 23 '15 at 06:18
  • possible duplicate of [Why doesn't returning 0x80000000 from a function that returns int32\_t cause a warning?](http://stackoverflow.com/questions/32656460/why-doesnt-returning-0x80000000-from-a-function-that-returns-int32-t-cause-a-wa) –  Sep 23 '15 at 06:22
  • 1
    It would help if you posted the warning message. – juanchopanza Sep 23 '15 at 06:22
  • @juanchopanza the question was why there *isn't any* ... and it was asked before. short answer, warning will be there with `-Wconversion`. –  Sep 23 '15 at 06:23
  • @FelixPalmen I was referring to "especially since clang 3.7.0 does generate a warning.". – juanchopanza Sep 23 '15 at 06:24
  • Just as a matter of interest... does anyone know what the compcert compiler will do with this? – BitTickler Sep 23 '15 at 06:30
  • @juanchopanza I added the warnings! @FelixPalmen `-Wconversion` did not change anything. – damwdan Sep 23 '15 at 06:47
  • 3
    `-Wsystem-headers` "fixes" it, the compiler uses the wrong location for the diagnostic (the one from the macro definition). Please file a bug report in gcc's bugzilla. – Marc Glisse Sep 23 '15 at 20:25

3 Answers3

3

This appears to be a regression in gcc 5.2.0 -- and, as far as I can tell, a weird one.

With gcc 4.4.5 and 4.8.4, the program (after adding the required #include <stddef.h>) produces warnings on both return NULL; statements, even without any extra command-line options.

With gcc 5.2.0, no warning is produced, even with gcc -c -Wall -Wextra -std=c99 -pedantic. For the second one, which returns a value from a void function, a diagnostic is mandatory.

Now here's the weird part.

$ gcc --version | head -n 1
gcc (GCC) 5.2.0
$ cat c.c
#include <stddef.h>

int function(void) {
#ifdef USE_NULL
   return NULL;
#else
    return ((void*)0);
#endif
}

void procedure(void) {
#ifdef USE_NULL
   return NULL;
#else
    return ((void*)0);
#endif
}
$ gcc -c c.c
c.c: In function ‘function’:
c.c:7:12: warning: return makes integer from pointer without a cast [-Wint-conversion]
     return ((void*)0);
            ^
c.c: In function ‘procedure’:
c.c:15:12: warning: ‘return’ with a value, in function returning void
     return ((void*)0);
            ^
$ gcc -c -DUSE_NULL c.c
$ 

When USE_NULL is defined, no warnings are produced. Compiling with gcc -E -DUSE_NULL (which prints the preprocessor's output to stdout) confirms that NULL is defined as ((void*)0). But when I replace NULL with ((void*)0), the warnings are produced (as they should be).

I don't know what's going on. Once the macro NULL has been expanded, it should be indistinguishable from ((void*)0), and yet the compiler's behavior changes depending on which is used.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

The validity of the first function is dependent on how NULL is defined. There's no problem with the first function if NULL is defined as 0. But if it happens to be defined as (void *) 0 (which is normally the case in C code) the first function becomes invalid. GCC is often very permissive about implicit pointer-to-integer conversions.

The second function is flat out invalid. The language specification clearly states that "A return statement with an expression shall not appear in a function whose return type is void." If it compiles, it must be another example of GCC being overly permissive about something.

You need to run GCC in -pedantic mode if you want its diagnostic output to be related to standard C language. In default mode it is not a credible C compiler (at least in therms of its diagnostic output) and the fact that it "does not issue a warning" means absolutely nothing.

Yet in my experiments I was not able to make GCC complain about the second function even with -std= and -pedantic switches. It looks like a bug in the compiler.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

I filled a bug report here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67730

It was confirmed and is fixed for 5.3 it seems!

Thanks for your help.

CL.
  • 173,858
  • 17
  • 217
  • 259
damwdan
  • 71
  • 5