bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: clang and _Noreturn


From: Bruno Haible
Subject: Re: clang and _Noreturn
Date: Sun, 23 Apr 2017 12:45:54 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-72-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

Thanks for explaining.

> > What is the semantic difference between _Noreturn and
> > __attribute_noreturn__?
> 
> __attribute__ ((__noreturn__)), which the latter expands to, also works with 
> function pointers, whereas _Noreturn does not. The distinction can matter 
> when a 
> function's address is assigned to a function pointer. Clang checks for 
> __attribute__ ((__noreturn__)) compatibility when assigning function 
> pointers; 
> GCC does not, which can lead to weird results.  For example:
> 
> _Noreturn void nr (void) { for (;;); }
> __attribute__ ((__noreturn__)) void anr (void) { for (;;); }
> 
> /* Valid.  */
> void (*a) (void) = nr;
> void (*b) (void) = anr;
> __attribute__ ((__noreturn__)) void (*c) (void) = anr;
> 
> /* Invalid, as _Noreturn applies only to function definitions.  */
> _Noreturn void (*d) (void) = nr;
> _Noreturn void (*e) (void) = anr;
> 
> /* Allowed by GCC, but weirdly disallowed by clang because f is not declared 
> with
>     __attribute__ ((__noreturn__)).  */
> __attribute__ ((__noreturn__)) void (*f) (void) = nr;
> 
> GCC does a better job in this area

I agree with your findings. In C mode I get this:
===============================================================================
void func1 (void) { for (;;); }
_Noreturn void func2 (void) { for (;;); }
__attribute__ ((__noreturn__)) void func3 (void) { for (;;); }

void (*fptr11) (void) = func1; /* GCC: OK clang: OK */
void (*fptr12) (void) = func2; /* GCC: OK clang: OK */
void (*fptr13) (void) = func3; /* GCC: OK clang: OK */

_Noreturn void (*fptr21) (void) = func1; /* GCC: warning clang: error */
_Noreturn void (*fptr22) (void) = func2; /* GCC: warning clang: error */
_Noreturn void (*fptr23) (void) = func3; /* GCC: warning clang: error */

__attribute__ ((__noreturn__)) void (*fptr31) (void) = func1; /* GCC: warning 
clang: warning */
__attribute__ ((__noreturn__)) void (*fptr32) (void) = func2; /* GCC: OK clang: 
warning */
__attribute__ ((__noreturn__)) void (*fptr33) (void) = func3; /* GCC: OK clang: 
OK */
===============================================================================

In C++ mode, you have to write '[[noreturn]]' instead of _Noreturn, and GCC
has a number of bugs in this area:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79604
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80495
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80496

> it's not clear that it's worth catering to clang's idiosyncracies here.

I disagree:
1) If _Noreturn does not apply to function pointers, only to functions, we
   should better avoid it. It's an ill-defined standard's feature.
2) What you call "clang's idiosyncracies" is triggered by our inconsistent use
   in obstack.c: In one place we use _Noreturn, in the other place we use
   __attribute__ ((__noreturn__)).
   In fact, even the GCC documentation does not state that _Noreturn on a
   function is equivalent to __attribute__ ((__noreturn__)).

So, at least for obstack.c, I propose to be consistent: use only
__attribute__ ((__noreturn__)).


2017-04-23  Bruno Haible  <address@hidden>

        obstack: Avoid clang warning due to inconsistent use of _Noreturn.
        The code was assuming that _Noreturn and __attribute__((__noreturn__))
        are equivalent on function definitions, which happens to be true (but
        undocumented) for GCC, but not for clang.
        * lib/obstack.c (print_and_abort): Use __attribute_noreturn__.

diff --git a/lib/obstack.c b/lib/obstack.c
index 1c7e069..49a846c 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -326,7 +326,7 @@ int obstack_exit_failure = EXIT_FAILURE;
 #   include <libio/iolibio.h>
 #  endif
 
-static _Noreturn void
+static __attribute_noreturn__ void
 print_and_abort (void)
 {
   /* Don't change any of these strings.  Yes, it would be possible to add




reply via email to

[Prev in Thread] Current Thread [Next in Thread]