[cfe-dev] clang for Windows problem in Boost.TypeTraits
Hans Wennborg
hans at chromium.org
Thu Oct 3 03:57:57 PDT 2013
I've filed http://llvm.org/bugs/show_bug.cgi?id=17464 to track this.
- Hans
On Wed, Oct 2, 2013 at 4:30 AM, Paweł Bylica <chfast at gmail.com> wrote:
>
>
>
> 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
>>> <mailto: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.
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
More information about the cfe-dev
mailing list