llvm/llvm-project

__has_declspec_attribute falsely reports some attrs as supported for MinGW and Cygwin targets

Closed this issue · 3 comments

Bugzilla Link 50614
Version 12.0
OS Linux
Attachments Repro
CC @zygoloid

Extended Description

It is true that the warnings for this specific repro can be silenced by adding the -fms-extensions option, but this option causes other problems in practice (causing function redefinition errors) and so I think I cannot use it.

$ cat mingw-declspec.c

#if __has_declspec_attribute(noalias)
__declspec(noalias)
#else
#warning no declspec noalias
#endif
void foo(void *a, void *b);

struct
#if __has_declspec_attribute(align)
__declspec(align(8))
#else
#warning no declspec align
#endif
bar { int i, j; } baz;

$ clang --target=x86_64-w64-mingw32 -fdeclspec -c mingw-declspec.c
mingw-declspec.c:3:12: warning: unknown attribute 'noalias' ignored [-Wunknown-attributes]
__declspec(noalias)
^~~~~~~
:343:38: note: expanded from here
#define __declspec(a) attribute((a))
^
mingw-declspec.c:11:12: warning: unknown attribute 'align' ignored [-Wunknown-attributes]
__declspec(align(8))
^~~~~~~~
:343:38: note: expanded from here
#define __declspec(a) attribute((a))
^
2 warnings generated.

I reproduced something similar.
It seems to be the same bug,
but I reproduced it in MacOS.

Originally received a report in Nginx Unit nginx/unit#653,
and later reported to ruby(1) https://bugs.ruby-lang.org/issues/18616,
it now seems to me a clang(1) bug.

Reproducer:

$ cat declspec.c 
#include <stdio.h>

int main(void)
{
	printf("%i\n", __has_declspec_attribute(noreturn));
}
$ cat declspec2.c 
#include <stdlib.h>

__declspec(noreturn) void foo(void)
{
	exit(0);
}

In Debian:

$ clang -Wall -Wextra declspec.c
$ ./a.out 
0
$ clang -Wall -Wextra -fdeclspec declspec.c
$ ./a.out 
1
$ clang -Wall -Wextra -S declspec2.c 
declspec2.c:3:1: error: '__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to enable support for __declspec attributes
__declspec(noreturn) void foo(void)
^
1 error generated.
$ clang -Wall -Wextra -S -fdeclspec declspec2.c 
$ clang -v
Debian clang version 13.0.1-3
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/10
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64

In MacOS:

$ clang -Wall -Wextra declspec.c 
$ ./a.out 
1
$ clang -Wall -Wextra -fdeclspec declspec.c 
$ ./a.out 
1
$ clang -Wall -Wextra -S declspec2.c 
declspec2.c:3:1: error: '__declspec' attributes are not enabled; use '-fdeclspec' or '-fms-extensions' to enable support for __declspec attributes
__declspec(noreturn) void foo(void)
^
1 error generated.
$ clang -Wall -Wextra -fdeclspec -S declspec2.c
$ clang -v
Apple clang version 13.0.0 (clang-1300.0.29.30)
Target: x86_64-apple-darwin20.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

It seems that ruby(1) knew about this bug in clang(1),
and they introduced -fdeclspec as a workaround back in 2019:
ruby/ruby@0958e19

@alejandro-colomar:
As of ef3800e, __has_declspec_attribute(x) will always return false when __declspec is not enabled (i.e. without -fdeclspec). If the behaviour of Apple Clang is different, that sounds like a bug specific to Apple Clang which should be reported to Apple (I am unfamiliar with how Apple handles __declspec.)

The original bug report refers to a different issue, caused by a built-in #define __declspec(a) attribute((a)) specifically added for MinGW/Cygwin targets incorrectly when -fdeclspec is enabled. I've submitted a fix: https://reviews.llvm.org/D135027