<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Oct 2, 2013 at 1:01 PM, Edward Diener <span dir="ltr"><<a href="mailto:eldlistmailingz@tropicsoft.com" target="_blank">eldlistmailingz@tropicsoft.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="im">On 10/1/2013 9:13 PM, Reid Kleckner wrote:<br>


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

</blockquote><div><br></div><div>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.</div><div><br></div><div>

In other words:</div><div><span style="font-family:Consolas;color:blue">void</span><span style="color:black;font-family:Consolas"> (*</span><span style="font-family:Consolas;color:rgb(43,145,175)">fp</span><span style="color:black;font-family:Consolas">)(...)</span></div>

<div>is the same as</div><div><span style="font-family:Consolas;color:blue">void</span><span style="color:black;font-family:Consolas"> (</span><span style="font-family:Consolas;color:blue">__fastcall</span><span style="color:black;font-family:Consolas">*</span><span style="font-family:Consolas;color:rgb(43,145,175)">fp</span><span style="color:black;font-family:Consolas">)(...)</span></div>

<div>and</div><div><span style="font-family:Consolas;color:blue">void</span><span style="color:black;font-family:Consolas"> (</span><span style="font-family:Consolas;color:blue">__stdcall</span><span style="color:black;font-family:Consolas">*</span><span style="font-family:Consolas;color:rgb(43,145,175)">fp</span><span style="color:black;font-family:Consolas">)(...)</span></div>

<div><br></div><div>You can even write:</div><div><pre style="font-family:Consolas;color:black"><span style="color:blue">void</span> <span style="color:blue">__stdcall</span> test(...) {}
<span style="color:blue">typedef</span> <span style="color:blue">void</span> (<span style="color:blue">__fastcall</span>*<span style="color:rgb(43,145,175)">fp</span>)(...);
<span style="color:rgb(43,145,175)">fp</span> f = &test;</pre></div></div><div class="gmail_extra">One more proof:</div><div class="gmail_extra"><pre style="font-family:Consolas;color:black"><span style="color:blue">void</span> (<span style="color:blue">__fastcall</span>*f)(...) = 1;
</pre></div><div class="gmail_extra">produces error: cannot convert from 'int' to 'void (__cdecl *)(...)'.</div><div class="gmail_extra"><br></div>I believe this template specialization really make no sense. </div>

<div class="gmail_extra"><br></div><div class="gmail_extra">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.</div>

</div>