[1/2] Add __clang_has_extension to sys/cdefs.h.

Message ID 7d28608ab5396836526b235526e0b757236cfc85.1461444595.git.zackw@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg April 22, 2016, 11:05 p.m. UTC
  clang provides an intrinsic __has_extension() to #if statements, useful
for feature detection.  Other compilers may throw a syntax error on

    #if defined __clang__ && __has_extension(...)

even though they do not need to evaluate the right-hand side of the
logical AND.  __clang_has_extension(...) therefore expands to
__has_extension(...) when __clang__ is defined, and to 0 otherwise.

	* misc/sys/cdefs.h: New utility macro __clang_has_extension.
---
 misc/sys/cdefs.h | 9 +++++++++
 1 file changed, 9 insertions(+)

2.8.1
  

Comments

Florian Weimer April 25, 2016, 7:22 a.m. UTC | #1
On 04/23/2016 01:05 AM, Zack Weinberg wrote:
> 	* misc/sys/cdefs.h: New utility macro __clang_has_extension.

I don't feel strongly about this, but the identifier looks like it's in 
the Clang namespace.  Perhaps use __glibc_clang_has_extension instead?

Florian
  
Zack Weinberg April 25, 2016, 1:57 p.m. UTC | #2
On Mon, Apr 25, 2016 at 3:22 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 04/23/2016 01:05 AM, Zack Weinberg wrote:
>>
>>         * misc/sys/cdefs.h: New utility macro __clang_has_extension.
>
> I don't feel strongly about this, but the identifier looks like it's in the
> Clang namespace.  Perhaps use __glibc_clang_has_extension instead?

That's a good point, but I think the name __glibc_clang_has_extension is
far too clunky to tolerate.

Experimenting, clang treats __has_extension as an intrinsic *macro* --
for instance, #ifdef __has_extension is true.  So maybe we could just do

#ifndef __has_extension
#define __has_extension(...) 0
#endif

and that would be good enough? It seems consistent with the way
sys/cdefs.h handles macro wrappers for GCC extensions.

zw
  
Florian Weimer April 26, 2016, 1:48 p.m. UTC | #3
On 04/25/2016 03:57 PM, Zack Weinberg wrote:

> Experimenting, clang treats __has_extension as an intrinsic *macro* --
> for instance, #ifdef __has_extension is true.  So maybe we could just do
>
> #ifndef __has_extension
> #define __has_extension(...) 0
> #endif
>
> and that would be good enough?

This will confuse application that checks for the presence of 
__has_extension.  glibc should not provide compiler-defined macros 
coming from non-GNU compilers because it will be difficult to coordinate 
with these parties (it's sometimes even difficult with GCC).

Florian
  
Paul Eggert April 26, 2016, 3:13 p.m. UTC | #4
On 04/26/2016 06:48 AM, Florian Weimer wrote:
>
> This will confuse application that checks for the presence of 
> __has_extension.

Yes. As an example of this sort of thing, GNU Emacs does this:

    #ifndef __has_attribute
    # define __has_attribute(a) __has_attribute_##a
    # define __has_attribute_alloc_size (4 < __GNUC__ + (3 <= 
__GNUC_MINOR__))
    # define __has_attribute_cleanup (3 < __GNUC__ + (4 <= __GNUC_MINOR__))
    ...

and this would stop working if Glibc sys/cdefs.h defined 
__has_attribute(x) to be 0 when compiling with GCC. This specific 
example is about __has_attribute and not __has_extension, but the same 
idea applies to __has_extension.
  
Roland McGrath April 28, 2016, 10:16 p.m. UTC | #5
I think this is a bad addition.  I don't think we want miscellaneous header
files to have Clang-specific #if checks.  What we really want is for header
files to do specific feature checks using some compiler-independent macros
defined by <sys/cdefs.h>.  This is also superior to the existing cases of
headers using __GNUC_PREREQ as a proxy for specific feature tests.

As Florian and Paul mentioned, new macros should avoid name space issues.
Just use the prefix __glibc_ on any new macro.

I think a generalized thing like __glibc_has_feature (foobar) would be
fine.  sys/cdefs.h can do a variety of macro magic things to map that to
what works in Clang and to __GNUC_PREREQ for GCC.  This is probably also
the best way to enable distros that backport features to their compilers to
update the corresponding conditionals easily, i.e. they can just patch
sys/cdefs.h in their glibc package to change some of these macro
definitions rather than dealing with the __GNUC_PREREQ mess throughout all
the headers.

You don't need to do the whole conversion for us, of course.  But look at
existing __GNUC_PREREQ tests and make sure that the scheme you come up with
will extend readily to cover all those cases.
  

Patch

diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index 7fd4154..b31878b 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -77,7 +77,15 @@ 
 
 #endif	/* GCC.  */
 
+/* Compilers that are not clang may object to
+       #if defined __clang__ && __has_extension (...)
+   even though they do not need to evaluate the right-hand side of the &&.  */
+#ifdef __clang__
+# define __clang_has_extension(ext) __has_extension (ext)
+#else
+# define __clang_has_extension(ext) 0
+#endif
+
 /* These two macros are not used in glibc anymore.  They are kept here
    only because some other projects expect the macros to be defined.  */
 #define __P(args)	args
--