Bug 89232

Summary: c++: Fail to build when <stdnoreturn.h> and the noreturn keyword is used
Product: gcc Reporter: pere
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: jakub
Priority: P3    
Version: 8.2.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description pere 2019-02-07 07:05:53 UTC
I ran into this issue while trying to prepare the coz profiler for Debian.

The <stdnoreturn.h> header file seem to be inefficient when using cc and
clang, be ignored causing an build error when using c++.

I found this example code on
<URL: http://en.cppreference.com/w/c/language/_Noreturn >, and it fail
to build with c++, but build with both cc and clang:

% cat > c++-noreturn.c <<EOF
#include <stdlib.h>
#include <stdio.h>
#include <stdnoreturn.h>
 
// causes undefined behavior if i <= 0
// exits if i > 0
noreturn void stop_now(int i) // or _Noreturn void stop_now(int i)
{
    if (i > 0) exit(i);
}
 
int main(void)
{
  puts("Preparing to stop...");
  stop_now(2);
  puts("This code is never executed.");
}
EOF
% gcc c++-noreturn.c 
c++-noreturn.c: In function 'stop_now':
c++-noreturn.c:10:1: warning: 'noreturn' function does return
 }
 ^
% ./a.out 
Preparing to stop...
% c++ c++-noreturn.c 
c++-noreturn.c:7:1: error: 'noreturn' does not name a type
 noreturn void stop_now(int i) // or _Noreturn void stop_now(int i)
 ^~~~~~~~
c++-noreturn.c: In function 'int main()':
c++-noreturn.c:15:13: error: 'stop_now' was not declared in this scope
   stop_now(2);
             ^
% clang c++-noreturn.c 
c++-noreturn.c:10:1: warning: function declared 'noreturn' should not return [-Winvalid-noreturn]
}
^
1 warning generated.
%

Perhaps something that should be fixed?

This issue is also reported as https://bugs.debian.org/833931 and has been present since at least gcc 6.  I find https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53182 related to the user of <stdnoreturn.h>, but it seem to be a different issue.

-- 
Happy hacking
Petter Reinholdtsen
Comment 1 Jonathan Wakely 2019-02-07 08:53:19 UTC
>stdnoreturn.h> is a C header, not part of C++, and not supported in C++.

The equivalent feature in C++ is an attribute:

[[noreturn]] void stop_now(int i);
Comment 2 pere 2019-02-07 09:58:08 UTC
Aha.  I thought valid C code would also be valid C++ code, and this belief became stronger when clang (and clang++) would accept the code.  Is there a list of C headers not supported by C++?
Comment 3 Jonathan Wakely 2019-02-07 10:34:24 UTC
The standard C++ headers are listed at:
https://en.cppreference.com/w/cpp/header

It does have an "Unsupported C headers" section:
https://en.cppreference.com/w/cpp/header#Unsupported_C_headers

"The C headers <stdatomic.h>, <stdnoreturn.h>, and <threads.h> are not included in C++ and have no cxxx equivalents."
Comment 4 Jonathan Wakely 2019-02-07 10:38:53 UTC
The reason you get a warning from cc (and clang) is that your function sometimes returns, which would lead to undefined behaviour. You are misusing noreturn.

The noreturn specifier/attribute means the function *never* returns, it is not to be used for functions which *sometimes* don't return. Any function is allowed to call exit(), you're not supposed to mark such functions noreturn.

The C11 standard says:

A function declared with a _Noreturn function specifier shall not return to its caller.

Recommended practice
The implementation should produce a diagnostic message for a function declared with a _Noreturn function specifier that appears to be capable of returning to its caller.
Comment 5 pere 2019-02-08 12:34:45 UTC
Thank you for the explanation.  It is a lot clearer to me now.

One thing confuses me, though.  If <stdnoreturn.h> is not acceptable in C++,
why is there no warning from the compiler when it is included, instead of giving the strange complain when 'noreturn' is used later in the file.
Comment 6 Jakub Jelinek 2019-02-08 12:39:27 UTC
The header doesn't define the noreturn macro (and must not, because one needs to be able to e.g. use [[noreturn]] and if noreturn was say a macro defined to [[noreturn]], that wouldn't work very well).
I don't see why you are looking for a warning, you got an error that is fairly readable when you try to use it as if it were a macro.
Comment 7 pere 2019-02-08 13:25:14 UTC
I just think it would have been useful if the compiler said something
like 'header file <stdnoreturn.h> is not defined/available in C++' or
something like that.  It would provide feedback to the developer even if
'noreturn' is not used anywhere in the code to cause the error I ran
into.

Anywya, just an idea for you to consider, perhaps a feature request for
a different bug report. :)
Comment 8 Jonathan Wakely 2019-02-08 14:02:14 UTC
But you can include it in C++, because the header exists. If you just include it an do nothing, there's no problem (it's not part of the C++ standard and so your program is not portable, conforming C++, but it compiles).

The problem is that you tried to use the 'noreturn' specifier in your function, and that is not valid in C++.

Including a useless header that doesn't define anything in C++ is fairly harmless. Writing invalid C++ code is invalid, and that's what triggers an error.

The problem is not the header, it's your code.