wanyisunflower / googlemock

Automatically exported from code.google.com/p/googlemock
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

MOCK_METHOD with an std::pair argument doesn't compile with VS2010 #158

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This doesn't build with VS2010:

enum PolicyDomain {
  POLICY_DOMAIN_CHROME,
  POLICY_DOMAIN_EXTENSIONS,
};

typedef std::pair<PolicyDomain, std::string> PolicyNamespace;

class PolicyService {
 public:
  virtual void RegisterPolicyNamespace(const PolicyNamespace& ns);
};

class MockPolicyService : public PolicyService {
 public:
  MOCK_METHOD1(RegisterPolicyNamespace, void(const PolicyNamespace&));
};

This was built with chromium's unit_tests, which let gtest and gmock use the 
system's tr1::tuple.

The fine compiler output:

c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(127) 
:error C2440: 'initializing' : cannot convert from 'const policy::PolicyDomain' 
to 'const std::pair<_Ty1,_Ty2> &'

        with

        [

            _Ty1=policy::PolicyDomain,

            _Ty2=std::string

        ]

        Reason: cannot convert from 'const policy::PolicyDomain' to 'const policy::PolicyNamespace'

        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

        c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(356) : see reference to function template instantiation 'std::tr1::_Cons_node<_Car,_Cdr>::_Cons_node<const _Ty1&,const _Ty2&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&,std::tr1::_Nil&>(_Farg0,_Farg1,_Farg2,_Farg3,_Farg4,_Farg5,_Farg6,_Farg7,_Farg8,_Farg9)' being compiled

        with

        [

            _Car=const std::pair<policy::PolicyDomain,std::string> ,

            _Cdr=std::tr1::_Tuple_type<std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>::_Type,

            _Ty1=policy::PolicyDomain,

            _Ty2=std::string,

            _Farg0=const policy::PolicyDomain &,

            _Farg1=const std::string &,

            _Farg2=std::tr1::_Nil &,

            _Farg3=std::tr1::_Nil &,

            _Farg4=std::tr1::_Nil &,

            _Farg5=std::tr1::_Nil &,

            _Farg6=std::tr1::_Nil &,

            _Farg7=std::tr1::_Nil &,

            _Farg8=std::tr1::_Nil &,

            _Farg9=std::tr1::_Nil &

        ]

        e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-generated-function-mockers.h(97) : see reference to function template instantiation 'std::tr1::tuple<_Arg0>::tuple<policy::PolicyDomain,std::string>(const std::pair<_Ty1,_Ty2> &)' being compiled

        with

        [

            _Arg0=const std::pair<policy::PolicyDomain,std::string> ,

            _Ty1=policy::PolicyDomain,

            _Ty2=std::string

        ]

        e:\b\build\slave\win\build\src\testing\gmock\include\gmock\gmock-generated-function-mockers.h(92) : while compiling class template member function 'void testing::internal::FunctionMocker<Function>::Invoke(A1)'

        with

        [

            Function=void (const policy::PolicyNamespace &),

            A1=const policy::PolicyNamespace &

        ]

        e:\b\build\slave\win\build\src\chrome\browser\policy\mock_policy_service.h(20) : see reference to class template instantiation 'testing::internal::FunctionMocker<Function>' being compiled

        with

        [

            Function=void (const policy::PolicyNamespace &)

        ]

c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(127) 
:error C2439: 'std::tr1::_Cons_node<_Car,_Cdr>::_Value' : member could not be 
initialized

        with

        [

            _Car=const std::pair<policy::PolicyDomain,std::string> ,

            _Cdr=std::tr1::_Tuple_type<std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>::_Type

        ]

        c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple(170) : see declaration of 'std::tr1::_Cons_node<_Car,_Cdr>::_Value'

        with

        [

            _Car=const std::pair<policy::PolicyDomain,std::string> ,

            _Cdr=std::tr1::_Tuple_type<std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>::_Type

        ]

Original issue reported on code.google.com by joaodasilva@chromium.org on 31 Jan 2013 at 3:30

GoogleCodeExporter commented 9 years ago
Joao, judging from the errors, somewhere the code is trying to pass a 
PolicyDomain to where a PolicyNamespace is expected.  I don't see that in the 
code snippet you provided.

Can you try to reduce the actual code to a minimal repro and then post the 
complete, real code and the errors?

Original comment by w...@google.com on 31 Jan 2013 at 6:01

GoogleCodeExporter commented 9 years ago
I know it looks like that, that was also my first guess while trying to fix 
this. But this happens even with unused classes; here's a reduced repro:

#include <utility>

class Foo {
 public:
  MOCK_METHOD1(Bar, void(std::pair<int, int>));
};

Just having this in a header is enough to trigger the same compilation error 
(i.e. this class was never instantiated, nor were any expectations set on the 
Bar method). GCC compiles this just fine.

Original comment by joaodasilva@chromium.org on 1 Feb 2013 at 10:39

GoogleCodeExporter commented 9 years ago
Joao, I suspect that the bug is in code you didn't show me or in the build 
script.  What you showed in the comment is not the complete code (e.g. it 
doesn't #include gmock.h).  Could you please provide:

1. the *complete real code* (ideally as a file attachment s.t. we know which 
line number is which), and
2. the *complete compiler error messages* for the code in #1.

Ideally, you should also include the compiler command line arguments.  Thanks!

Original comment by w...@google.com on 1 Feb 2013 at 5:19

GoogleCodeExporter commented 9 years ago
The code from #2 is really sufficient to trigger the compilation failure. I 
previously built it by adding that code to a chromium unit tests; I've now 
reproduced this again by using the gmock_main project from gmock-1.6.0.zip:

- open the gmock solution
- "gmock" and "gmock_main" projects build just fine
  (I built from Visual Studio; right-click project, Build)
- now add the code from comment #2 to gmock_main.cc
- rebuilding fails

I've attached gmock_main.cc with the modifications and the compiler output.

Original comment by joaodasilva@chromium.org on 4 Feb 2013 at 9:43

Attachments:

GoogleCodeExporter commented 9 years ago
Joao, your version of gMock appears to be a bit out-dated.  The trunk head is 
at r412 now, and looks like this:

https://code.google.com/p/googlemock/source/browse/trunk/src/gmock_main.cc

I've made your change to the trunk head version of gmock_main.cc.  See the 
attachment for what it looks like.  I'm testing it on Windows now...

Original comment by w...@google.com on 4 Feb 2013 at 8:02

Attachments:

GoogleCodeExporter commented 9 years ago
The tests passed for me on Windows, using MSVC 8.0.  The log is at

https://pulse-internal.corp.google.com/dashboard/my/553/logs/stage/Continuous%20
Test%20gMock%20-%20Windows%20CMake%20Release/raw/true/

I'm not sure what is wrong in your case, Joao.  I suggest to try to update your 
gtest/gmock version to the latest.  If that doesn't help, perhaps work with 
some C++ guru familiar with Chrome build (e.g. Nico) to debug it.  Sorry.

Original comment by w...@google.com on 4 Feb 2013 at 8:13

GoogleCodeExporter commented 9 years ago
I tried this with an svn checkout; I got revision 412. I opened 
"googlemock-read-only\msvc\2010\gmock.sln" with Visual Studio 2010, and built 
all the projects; it compiled everything without problems.

Then I added this to gmock_main.cc:

#include <utility>

class Foo {
public:
    MOCK_METHOD1(Bar, void(std::pair<int, int>));
};

And recompiling fails with the same error. I've attached both the modified 
gmock_main.cc and the compiler output log. I suspect this is specific to the 
STL pair (and maybe tuple, see the log) shipped with VS2010. Can you try this 
with that version of Visual Studio?

(the complete version is 10.0.40219.1 SP1Rel)

Original comment by joaodasilva@chromium.org on 5 Feb 2013 at 10:18

Attachments:

GoogleCodeExporter commented 9 years ago
The problem lies within this tuple constructor (from C:\Program Files 
(x86)\vs100\VC\include\tuple)

    template<class _Farg0,
        class _Farg1>
        tuple(const pair<_Farg0, _Farg1>& _Right)
        : _Impl(_Right.first, _Right.second, _TAIL_2(_Nil_obj))
        {   // construct copy of _Right
        }

It is more special than the generic tuple constructor with two arguments 
synthesized by the xfwrap include some lines below

// construct from one or more arguments
#define _INCL_FILE_xxtuple0
#include <xfwrap>

Therefore, trying to construct a tuple<pair<T0, T1>> from a pair<T0, T1> 
results in a call to the first constructor mentioned above which in turn tries 
to assign T0 to pair<T0, T1>, yielding the error.

The solution would be to enable the tuple from pair constructor only if T0 and 
T1 from the pair<T0, T1> given as argument match T0 and T1 from the tuple<T0, 
T1> being constructed.

A quick look into the tuple implementation of Visual Studio 2012 revealed the 
bug being fixed as follows:

    template<class _First, \
        class _Second> \
        tuple(pair<_First, _Second>&& _Right, \
            typename enable_if<_Tuple_enable< \
                tuple<_First, _Second>, _Myt>::value, \
                void>::type ** = 0) \
        : _Mybase(tuple<_Second>(_STD forward<_Second>(_Right.second))), \
            _Myfirst(_STD forward<_First>(_Right.first)) \
        {   /* construct by moving pair */ \
        /* no static_assert necessary */ \
        } \

It should not be too hard to port this fix to Visual Studio 2010.

HTH

Original comment by debug...@gmail.com on 5 Feb 2013 at 3:02

GoogleCodeExporter commented 9 years ago
To clarify: the problem lies within the single argument tuple constructor 
implementation of Visual Studio 2010. 

I have corrected the tuple-from-pair-constructors, see attached patch file.

Original comment by debug...@gmail.com on 28 Feb 2013 at 8:56

Attachments:

GoogleCodeExporter commented 9 years ago
Another possibility might be to add an unused default parameter to the 
signature of the method to be mocked, so that gmock no longer tries to 
construct the parameter tuple from a single pair.

Original comment by debug...@gmail.com on 28 Feb 2013 at 11:28

GoogleCodeExporter commented 9 years ago
Closing this as it's a defect in MSVC and has a workaround.

Original comment by w...@google.com on 8 Mar 2013 at 5:29