MOCK_METHOD macro not working with clang-cl
My environment
- Windows 10 Pro version 1809 OS build 17763.775
- cmake 3.12.18081601-MSVC_2
- cl version 19.16.27034
- clang-cl versions 7.0.0 (tags/RELEASE_700/final), 8.0.0 (tags/RELEASE_800/final) and 9.0.0 (https://github.com/llvm/llvm-project.git 0399d5a9682b3cef71c653373e38890c63c4c365) (self-built clang from 9.0.0 tag)
- googletest 1.10.0
Steps to reproduce
- Start the x64 Native Tools Command Prompt for VS 2017
- Ensure clang-cl can be found in the PATH
- While in the top-level googletest directory, try to build using
mkdir build cd build cmake -Dgmock_build_tests=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -G "NMake Makefiles" .. cmake --build .
Error output (truncated)
[ 43%] Building CXX object googlemock/CMakeFiles/gmock-function-mocker_test.dir/test/gmock-function-mocker_test.cc.obj
C:\TEMP\googletest\googlemock\test\gmock-function-mocker_test.cc(127,3): error: static_assert failed
"(int n) should be enclosed in parentheses."
MOCK_METHOD(void, VoidReturning, (int n)); // NOLINT
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(43,3): note: expanded from macro
'MOCK_METHOD'
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(82,3): note: expanded from macro
'GMOCK_PP_VARIADIC_CALL'
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(18,30): note: expanded from macro
'GMOCK_PP_CAT'
#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)
^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(52,3): note: expanded from macro
'GMOCK_INTERNAL_MOCK_METHOD_ARG_3'
GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ())
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(55,3): note: expanded from macro
'GMOCK_INTERNAL_MOCK_METHOD_ARG_4'
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(84,3): note: expanded from macro
'GMOCK_INTERNAL_ASSERT_PARENTHESIS'
static_assert( \
^
C:\TEMP\googletest\googlemock\test\gmock-function-mocker_test.cc(127,3): error: static_assert failed
"() should be enclosed in parentheses."
MOCK_METHOD(void, VoidReturning, (int n)); // NOLINT
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(43,3): note: expanded from macro
'MOCK_METHOD'
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(82,3): note: expanded from macro
'GMOCK_PP_VARIADIC_CALL'
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(18,30): note: expanded from macro
'GMOCK_PP_CAT'
#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)
^
note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(52,3): note: expanded from macro
'GMOCK_INTERNAL_MOCK_METHOD_ARG_3'
GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ())
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(56,3): note: expanded from macro
'GMOCK_INTERNAL_MOCK_METHOD_ARG_4'
GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(84,3): note: expanded from macro
'GMOCK_INTERNAL_ASSERT_PARENTHESIS'
static_assert( \
^
C:\TEMP\googletest\googlemock\test\gmock-function-mocker_test.cc(127,3): error: static_assert failed
due to requirement '(0 + 0 + 0 + 0 + 0) == 1' " cannot be recognized as a valid specification modifier."
MOCK_METHOD(void, VoidReturning, (int n)); // NOLINT
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(43,3): note: expanded from macro
'MOCK_METHOD'
GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(82,3): note: expanded from macro
'GMOCK_PP_VARIADIC_CALL'
GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(18,30): note: expanded from macro
'GMOCK_PP_CAT'
#define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2)
^
note: (skipping 6 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all)
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(259,32): note: expanded from macro
'GMOCK_PP_INTERNAL_FOR_EACH_IMPL_1'
GMOCK_PP_INTERNAL_CALL_MACRO(_Macro, _i, _Data, GMOCK_PP_HEAD _Tuple)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/internal/gmock-pp.h(256,3): note: expanded from macro
'GMOCK_PP_INTERNAL_CALL_MACRO'
_Macro(_i, _Data, _element)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\TEMP\googletest\googlemock\include\gmock/gmock-function-mocker.h(158,3): note: expanded from macro
'GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT'
static_assert( \
^
I dug a little deeper into this and the reason seems to be that
GMOCK_PP_HAS_COMMA(,)
evaluates to 1 with MSVC and to 0 with clang-cl.
As I had already commented, #2514 does not fix this bug. In fact, the only way to fix this seems to be to write a version of MOCK_METHOD that does not use GMOCK_PP_HAS_COMMA(,).
@vslashg Can you reopen this please?
Any update on this?
https://reviews.llvm.org/D69626 fixed the bug in clangs msvc compatibility code. Clang 10, which is about to be released soon, should be able to compile code containing the MOCK_METHOD macro just fine. I don't think it is feasible, maybe not even possible, to work around that Clang bug in googletest code.
I tried compiling with clang 10 today and the same error popped up. It would be unfortunate if clang on windows is not an option for compiling gtest
I've also experienced this issue when building a c`++17 codebase that includes several MOCK_METHOD macros with the latest LLVM clang-cl release (10.0.0.0).
The chromium guys also use clang-cl for builiding chrome on windows. In their own issue tracker Issue 989095: Code using gMock fails to build on Windows they say that the only workaround is to use old style macros (MOCK_METHOD0...MOCK_METHOD9) which are deprecated. something like
MOCK_METHOD(void, classname,
(std::string& logsink, const std::string& fname, const std::string& fn, int ln,
std::string& txt, int level));
becomes something like this
MOCH_METHOD6(classname, void (std::string& logsink, const std::string& fname, const std::string& fn, int ln, std::string& txt, int level)
It would be interesting to revisit this issue. We are not rewriting our codebase to the old macros and this is preventing us from using google test with clang-cl at this point
I don't know what the issue actually is, but in case it's relevant, I worked around a bug with msvc a while back: https://github.com/google/googletest/commit/d2016469064bdb488ce271c84684518d2716fec2
If the root cause is the same, perhaps sticking enough , ...s to GMOCK_PP_INTERNAL_16TH (called from GMOCK_PP_HAS_COMMA) and whatever it calls may work around this.
This week we built a local copy of google test based on the newest commit available in gtest master branch (https://github.com/google/googletest/commit/356f2d264a485db2fcc50ec1c672e0d37b6cb39b). The good news is that this issue is fixed, as previously broken tests that call the MOCK_METHOD macros now work with clang-cl 10.0.0.0 on windows. Both visual studio solutions and ninja projects build & run our gtests.
We will base our work on https://github.com/google/googletest/commit/356f2d264a485db2fcc50ec1c672e0d37b6cb39b in our project until there is a newer stable release from google-test. Unfortunately the 1.10 release (https://github.com/google/googletest/commit/703bd9caab50b139428cea1aaff9974ebee5742e) from October 2019 is broken for us at this point...
This was fixed either Oct 11 2019 or Dec 16 2019 (https://bugs.chromium.org/p/chromium/issues/detail?id=989095#c19).
We are observing this issue is resolved on master, and can probably be marked resolved in 1.11.
Will 1.11 be ever released with this fix or at least 1.10.1?
should be in a release now, can probably be closed
Closing this. If you still see this issue please reopen.