googletest icon indicating copy to clipboard operation
googletest copied to clipboard

MOCK_METHOD macro not working with clang-cl

Open Corristo opened this issue 6 years ago • 13 comments

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(                                                          \
  ^

Corristo avatar Oct 04 '19 20:10 Corristo

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.

Corristo avatar Oct 06 '19 21:10 Corristo

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(,).

Corristo avatar Oct 23 '19 18:10 Corristo

@vslashg Can you reopen this please?

Corristo avatar Oct 25 '19 20:10 Corristo

Any update on this?

shyun3 avatar Mar 05 '20 19:03 shyun3

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.

Corristo avatar Mar 07 '20 10:03 Corristo

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

jackadrianglass avatar May 13 '20 22:05 jackadrianglass

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

aandaluz avatar May 25 '20 08:05 aandaluz

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.

ShabbyX avatar Jun 26 '20 04:06 ShabbyX

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...

aandaluz avatar Jul 09 '20 15:07 aandaluz

This was fixed either Oct 11 2019 or Dec 16 2019 (https://bugs.chromium.org/p/chromium/issues/detail?id=989095#c19).

nico avatar Sep 04 '20 17:09 nico

We are observing this issue is resolved on master, and can probably be marked resolved in 1.11.

wrowe avatar Sep 19 '20 20:09 wrowe

Will 1.11 be ever released with this fix or at least 1.10.1?

TheStormN avatar May 27 '21 11:05 TheStormN

should be in a release now, can probably be closed

keith avatar Aug 19 '22 17:08 keith

Closing this. If you still see this issue please reopen.

higher-performance avatar Oct 11 '22 20:10 higher-performance