[cfe-dev] clang for Windows problem in Boost.TypeTraits

Paweł Bylica chfast at gmail.com
Wed Oct 2 04:30:09 PDT 2013


On Wed, Oct 2, 2013 at 1:01 PM, Edward Diener <
eldlistmailingz at tropicsoft.com> wrote:

> On 10/1/2013 9:13 PM, Reid Kleckner wrote:
>
>> On Tue, Oct 1, 2013 at 8:27 PM, Edward Diener
>> <eldlistmailingz at tropicsoft.**com <eldlistmailingz at tropicsoft.com>
>> <mailto:eldlistmailingz@**tropicsoft.com <eldlistmailingz at tropicsoft.com>>>
>> wrote:
>>
>>     On 10/1/2013 2:16 PM, Nico Rieck wrote:
>>
>>         On 30.09.2013 05:29, Edward Diener wrote:
>>
>>             I could not find anything in the C++11 standard about
>>             variadic functions
>>             and calling conventions. Is this a "bug" with clang under
>>             Windows or
>>             should Boost.TypeTraits not try to allow __fastcall in this
>>             situation
>>             when compiling with clang under Windows ?
>>
>>
>>         I think it's a defect in both. Boost should drop the overloaded
>>         vararg
>>         is_function_ptr_tester specializations with non-standard calling
>>         conventions as they are never used. When MSVC encounters a vararg
>>         function with stdcall/fastcall it silently converts it to cdecl.
>>
>>
>>     is there a way to test that this is what it actually does ?
>>
>>
>> First, compiling the code "void __fastcall foo() { }" produces the
>> symbol ?foo@@YAXZZ which demangles to 'void __cdecl foo(...)'.
>>
>> Second, you can call it and verify that the assembly is adhering to the
>> usual C calling convention.
>>
>
> Understood.
>
>
>
>>
>>         Though
>>         for compatibility with (broken) MSVC code Clang should match that
>>         behavior if desired.
>>
>>
>>     The issue is that MSVC will accept the declaration without a
>>     compiler error as part of its extensions no matter what it may
>>     silently do. So if clang in Windows also defines the _MSC_EXTENSIONS
>>     macro it should ideally emulate MSVC in that regard.
>>
>>
>> I agree, this is a reasonable expectation, but I would classify this bug
>> as low priority, since variadic fastcall doesn't make sense.
>>
>
> I have brought this last point up in the Boost developers forum.
>
>
>
>>     I will however mention in the Boost developers forum that it might
>>     be good to drop the overloaded vararg specializations with
>>     non-standard calling conventions for MSVC. Or Boost could decide to
>>     test for clang and not allow it when using clang.
>>
>>
>> Boost probably should drop this specialization.  It's actually declaring
>> the __cdecl specialization after the implicit adjustment.  When I
>> attempt to define a specialization for both 'R (__fastcall *)(...)' and
>> 'R (__cdecl *)(...)' in the same TU, I get a compiler error from MSVC:
>> t.cpp(7) : error C2995: 'void is_function_template(R (__cdecl *)(...))'
>> : function template has already been defined
>>          t.cpp(5) : see declaration of 'is_function_template'
>>
>> extern "C" int printf(const char *fmt, ...);
>> template <typename T>
>> void is_function_template(T t) { printf("no\n"); }
>> template <typename R>
>> void is_function_template(R (__cdecl *fptr)(...)) { printf("cdecl\n"); }
>> template <typename R>
>> void is_function_template(R (__fastcall *fptr)(...)) {
>> printf("fastcall\n"); }
>>
>
> Yet just the declarations in the Boost header file does not give an MSVC
> compiler error:
>
>
> template <class R >
> yes_type is_function_ptr_tester(R (__fastcall*)( ...));
> template <class R >
> yes_type is_function_ptr_tester(R (__cdecl*)( ...));
>
> in the same TU. But I will bring up in the Boost forum that actually
> trying to define separate implementations in the same TU with those
> signatures does generate an MSVC error.
>
>
I did some research on pointers to __fastcall variadic functions. Type
declaration of such pointer is accepted by MSVS, but it means a pointer to
__cdecl function.

In other words:
void (*fp)(...)
is the same as
void (__fastcall*fp)(...)
and
void (__stdcall*fp)(...)

You can even write:

void __stdcall test(...) {}typedef void (__fastcall*fp)(...);fp f = &test;

One more proof:

void (__fastcall*f)(...) = 1;

produces error: cannot convert from 'int' to 'void (__cdecl *)(...)'.

I believe this template specialization really make no sense.

As far as clang is considered, it does not accept pointers to __fastcall
variadic function but accepts pointers for __stdcall variadic function.
Such template specialization exists in the same Boost file.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131002/e7bfd48c/attachment.html>


More information about the cfe-dev mailing list