[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
- clang and _Noreturn, Bruno Haible, 2017/04/22
- Re: clang and _Noreturn, Paul Eggert, 2017/04/22
- Re: clang and _Noreturn,
Bruno Haible <=
- Re: clang and _Noreturn, Paul Eggert, 2017/04/23
- Re: clang and _Noreturn, Bruno Haible, 2017/04/23
- Re: clang and _Noreturn, Paul Eggert, 2017/04/23
- Re: clang and _Noreturn, Bruno Haible, 2017/04/24
- Re: clang and _Noreturn, Paul Eggert, 2017/04/24
- Re: clang and _Noreturn, Bruno Haible, 2017/04/25
- Re: clang and _Noreturn, Paul Eggert, 2017/04/25
- Re: clang and _Noreturn, Bruno Haible, 2017/04/26
- Re: clang and _Noreturn, Bruno Haible, 2017/04/26