Hello,
I'm porting some existing C++ code to VS2005 C++/CLI.
When I compile the following code with "No CLR support" it behaves as
expected (1 + 2 = 3) in all cases. When I compile it with /clr then
transform call using addFunc<int> suggests that 1 + 2 = 8b001cc4.
Anyone know what's going on?
Thanks,
Richard.
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
// fixed type addition function.
int addInt32Func(const int& lhs,const int& rhs)
{
return lhs + rhs;
}
// template version of addition function
template<typename T> T addFunc(const T& lhs,const T& rhs)
{
return lhs + rhs;
}
// functor version of addition function
template<typename T> class addClass : public binary_function<T, T, T>
{
public:
result_type operator()(
const first_argument_type& lhs,
const second_argument_type& rhs)
{
return (result_type)(lhs + rhs);
}
};
int main(int argc, char* argv[])
{
cout << "Single values " << endl;
int a = 1, b = 2, c;
c = addInt32Func(a, b);
cout << " addInt32Func "
<< hex << a << " + " << b << " = " << c << endl;
c = addFunc<int>(a, b);
cout << " addFunc<int> "
<< hex << a << " + " << b << " = " << c << endl;
c = addClass<int>()(a, b);
cout << " addClass<int>::addFunc "
<< hex << a << " + " << b << " = " << c << endl;
cout << "Transform vector values" << endl;
const int = 2;
vector<int> av(N_ELEM, 1), bv(N_ELEM, 2), cv(N_ELEM);
std::transform(av.begin(),av.end(),bv.begin(),cv.begin(),addInt32Func);
cout << " addInt32Func "
<< hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
std::transform(av.begin(),av.end(),bv.begin(),cv.begin(),addFunc<int>);
cout << " addFunc<int> "
<< hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
std::transform(av.begin(),av.end(),bv.begin(),cv.begin(),addClass<int>());
cout << " addClass<int>() "
<< hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
}
Barry Kelly - 27 Jul 2006 12:55 GMT
> When I compile the following code with "No CLR support" it behaves as
> expected (1 + 2 = 3) in all cases. When I compile it with /clr then
> transform call using addFunc<int> suggests that 1 + 2 = 8b001cc4.
>
> Anyone know what's going on?
Interesting program sample. It looks awfully like a C++ compiler bug,
the problem being it's not always checking the calling convention of the
function template.
When compiled either without any CLR support, or with -clr:pure support,
it works. In mixed mode (i.e. just -clr), it doesn't work. Of course, it
doesn't even compile with -clr:safe.
I tried changing the templated function to a generic function - and in
that case, the problem goes away:
---8<---
generic<typename T> T addFunc(T lhs, T rhs)
{
return lhs + rhs;
}
--->8---
Alternatively, sticking the function into a function pointer temporarily
also works:
---8<---
int (*f)(const int&, const int&) = addFunc<int>;
std::transform(av.begin(),av.end(),bv.begin(),cv.begin(),f);
cout << " f "
<< hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
--->8---
Finally, changing the calling convention to __clrcall also works:
---8<---
template<typename T>
T __clrcall addFunc(const T &lhs, const T &rhs)
{
return lhs + rhs;
}
// ...
int (__clrcall *f)(const int&, const int&) = addFunc<int>;
--->8---
I'd say you can file a bug based on your info.
-- Barry

Signature
http://barrkel.blogspot.com/
Barry Kelly - 27 Jul 2006 13:05 GMT
> I'd say you can file a bug based on your info.
Forgot to mention location: http://connect.microsoft.com/
-- Barry

Signature
http://barrkel.blogspot.com/
Richard B68 - 27 Jul 2006 13:37 GMT
> I'd say you can file a bug based on your info.
>
> -- Barry
Done.
Thanks for the validation.
Holger Grund - 27 Jul 2006 14:35 GMT
> When I compile the following code with "No CLR support" it behaves as
> expected (1 + 2 = 3) in all cases. When I compile it with /clr then
> transform call using addFunc<int> suggests that 1 + 2 = 8b001cc4.
[..]
> std::transform(av.begin(),av.end(),bv.begin(),cv.begin(),addInt32Func);
> cout << " addInt32Func "
[quoted text clipped - 3 lines]
> cout << " addFunc<int> "
> << hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
I think I might have seen something like this. I had an issue once and
looked only very briefly into it. But I seem to recall managed code
indirectly calling into managed code via a double thunk
(caller=>Managed to Native=>Native to Managed=>callee)
where some of the thunking code clobbered an allocated register.
It might be the same issue for you. IIRC a free function would
be called via a statically declared virtual thunk while the template
specialization has its address taken via ldftn. I thought the CLR
should handle both cases in the same way, but apparently it
did not.
All that being said, I didn't have the time to look into it.
-hg
Richard B68 - 02 Aug 2006 08:30 GMT
Submitted as ID 171949 on connect.microsoft.com but it's all gone a bit dark.
This shook my confidence in the compiler enough that I'll be sticking with
unmanaged C++ for a while.
> Hello,
> I'm porting some existing C++ code to VS2005 C++/CLI.
[quoted text clipped - 74 lines]
> << hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
> }
Richard B68 - 06 Sep 2006 08:55 GMT
ID 171949 was close "Won't fix" without comment.
Don't think I'll bother reporting any more bugs if that's the response.
> Submitted as ID 171949 on connect.microsoft.com but it's all gone a bit dark.
>
[quoted text clipped - 79 lines]
> > << hex << av[0] << " + " << bv[0] << " = " << cv[0] << endl;
> > }