On 10/2/2013 2:28 PM, Stephan T. Lavavej wrote:
[Edward Diener]
Nonetheless VC++ ( 8, 9, 10, and 11 ) does not produce a compiler error when a __stdcall or __fastcall calling convention is used in a pointer to function taking old-style varags. Do you see this as an ongoing bug in VC++ ?
According to my understanding, it's a "feature", not a bug (but also not a feature).
The problem from clang's perspective is that they must emulate this "feature" <g> to compile Boost type_traits. Their developers feel that Boost type_traits should not depend on this feature, ie. should not specify any VC++ calling conventions for varargs function or function template declarations.
This is vaguely similar to how C++ immediately rewrites array parameters in functions to pointer parameters (and function parameters to function pointer parameters, and drops const on value parameters as far as outside callers are concerned). Different syntax results in the same type being emitted.
If so Boost type_traits should not support it AFAICS.
There is nothing to support, because the types are identical as far as templates are concerned:
What I mean is that in VC++ the declarations are redundant, being the same template redeclared. In type_traits is_function_ptr_tester.hpp the lines: template <class R > yes_type is_function_ptr_tester(R (__stdcall*)( ...)); template <class R > yes_type is_function_ptr_tester(R (__fastcall*)( ...)); template <class R > yes_type is_function_ptr_tester(R (__cdecl*)( ...)); are just redeclaring the same function template, whereas template <class R > yes_type is_function_ptr_tester(R (__stdcall*)()); template <class R > yes_type is_function_ptr_tester(R (__fastcall*)()); template <class R > yes_type is_function_ptr_tester(R (__cdecl*)()); are different function templates.
C:\Temp>type meow.cpp #include <iostream> #include
using namespace std; int main() { cout << boolalpha; cout << is_same
::value << endl; cout << is_same ::value << endl; cout << is_same ::value << endl; cout << is_same ::value << endl; } C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp meow.cpp
C:\Temp>meow true true true true
The list is appreciated. But were old-style varargs included in your tests ?
Yes. As I noted, they are an exception - when I specialize our type traits for old-style varargs, I don't apply any explicit calling convention, because I was unable to find anything that made the types physically different.
Understood.
I have not tried VC in VS2013, but the matter should be cleared up so that VC++ at least does not at accept the __fastcall calling convention with old-style varags if what you say in the first line of your reply is true.
This is not the only place where VC looks at a calling convention and decides to silently rewrite it. As I recall, VC does this for non-vararg functions on x64 too (I would have to dig up my notes to find the exact examples).
From a library author perspective, this rewriting doesn't matter. You just want to be able to provide a set of specializations such that users (potentially saying calling conventions that get rewritten) always activate one of your specializations.
I believe I have achieved this in VC 2013 - std::is_function and std::is_member_function_pointer should always return true regardless of the user-written calling convention (with the exception of __vectorcall; I have fixed that for post-2013-RTM). Boost can achieve the exact same thing.
Thanks for the information. Boost is more complicated than just VC++. It has to support other compilers, even with VC++ calling conventions. In this case clang either has to change to be like VC++ and treat all calling conventions with varargs functions and function templates as if no calling convention existed or Boost type_traits should change and eliminate the redundant function templates in is_function_ptr_tester.hpp when varargs declarations are specified.