[cfe-dev] Invalid noreturn

Charles Davis cdavis at mymail.mines.edu
Thu Dec 17 14:35:45 PST 2009

Filipe Cabecinhas wrote:
> Hi.
> I was trying to compile git with clang but it yielded the "function 
> declared 'noreturn' should not return" error. Here is a small test case:
> [filcab at Farnsworth ~] $ cat a.c
> #include <stdio.h>
> #include <stdlib.h>
> #define NORETURN __attribute__((__noreturn__))
> extern void a(void);
> static NORETURN void die_builtin(int err)
> {
>          exit(128);
> }
> static NORETURN void (*die_routine)(int i) = die_builtin;
> extern NORETURN void die(int err);
> void die (int err)
> {
>    die_routine(err);
>    a();
> }
> extern NORETURN void aaa(int err);
> void aaa(int err)
> {
>    exit(1);
>    a();
> }
> [filcab at Farnsworth ~] $ clang -c a.c
> a.c:20:1: warning: function declared 'noreturn' should not return
>        [-Winvalid-noreturn]
> }
> ^
> 1 diagnostic generated.
> [filcab at Farnsworth ~] $
> Is this supposed to be like this? Or is it a bug? If I call a noreturn 
> function pointer, I get the warning. If I call exit(), I don't.
> I was expecting both to have the same behaviour.
> The code where I saw this had a die() function which received a va_list. 
> After calling this die() function, they "called" the macro va_close() 
> and this triggered the warning.
I thought I fixed this!

It seems to be related to what happens after the call to the noreturn
function pointer. If there's nothing after it, it doesn't warn, but if
there's something after it, it does warn.

Here's another useful and interesting tidbit: if you put the noreturn
attribute inside the parentheses with the function name, or after the
parameter list, the problem goes away:

static void (NORETURN *die_routine)(int i); /* this works */
static void (*die_routine)(int i) NORETURN; /* so does this */
static NORETURN void (*die_routine)(int i); /* but not this */
static void NORETURN (*die_routine)(int i); /* and not this */

The reason is that, when clang sees the noreturn in the second two
cases, it hasn't yet seen the whole function header yet, so it tries (in
vain) to apply it to the return type. What we really want is for clang
to try to apply it to the function type, not the type it returns. I need
to figure this out anyway, so calling convention attributes work
properly in my future patches.


More information about the cfe-dev mailing list