google / googletest

GoogleTest - Google Testing and Mocking Framework
https://google.github.io/googletest/
BSD 3-Clause "New" or "Revised" License
34.9k stars 10.16k forks source link

QNX compilation failure of .WillOnce() #3947

Open mnil opened 2 years ago

mnil commented 2 years ago

Describe the bug

During an uplift of our gtest version we got compilation failures for our QNX compiler but not for gcc or clang. I bisected it to this commit: https://github.com/google/googletest/commit/0498660ea575bfeb4b3b0879fa6aa6904d1df373 by @jacobsa.

Steps to reproduce the bug

The following works on gcc and clang but not on QNX 7:

#include <gmock/gmock.h>
#include <gtest/gtest.h>

class Turtle
{
 public:
    Turtle() {}
    virtual ~Turtle() {}
    virtual int age() const = 0;
};

class MockTurtle : public Turtle
{
 public:
    MOCK_METHOD(int, age, (), (const, override));
};

TEST(Turtle, TurtleAgeTest)
{
    MockTurtle turtle;
    EXPECT_CALL(turtle, age()).WillOnce(::testing::Return(1));
    turtle.age();
}

Changing .WillOnce() to .WillRepeatedly() makes it compile on all our platforms.

Does the bug persist in the most recent commit?

Verified that it fails on: bea621c3c39d8a7f71f07bd543c3a58bfa684f92

What operating system and version are you using?

Ubuntu 18.04.

What compiler and version are you using?

QNX 7.

What build system are you using?

Bazel 5.1.1.

Additional context

BUILD.bazel

cc_test(
    name = "foo",
    srcs = [
        "foo.cpp",
    ],
    deps = [
        "@googletest//:gtest_main",
    ],
)

Error message:

$ bazel build --config=aarch64_qnx_qcc //:foo
INFO: Invocation ID: c62e4d54-c742-4b31-8bd8-5892fc173d93
INFO: Analyzed target //:foo (<redacted>).
INFO: Found 1 target...
ERROR: /<redacted>/BUILD.bazel:8:10: Compiling foo.cpp failed: (Exit 1): qcc failed: error executing command external/qnx/qcc -V5.4.0,gcc_ntoaarch64le -Wc,-fstack-protector-strong -Wc,-fno-omit-frame-pointer -Wc,-fno-var-tracking '-Wc,-fmessage-length=0' -fno-math-errno -Wc,-fasynchronous-unwind-tables ... (remaining 50 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox
In file included from external/googletest/googlemock/include/gmock/gmock.h:56:0,
                 from foo.cpp:1:
external/googletest/googlemock/include/gmock/gmock-actions.h: In instantiation of 'struct testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >':
external/googletest/googlemock/include/gmock/gmock-actions.h:284:8:   required from 'struct testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, std::__1::tuple<testing::OnceAction<int()>&&> > >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >, testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >'
external/googletest/googlemock/include/gmock/gmock-actions.h:476:30:   required by substitution of 'template<class Callable, typename std::__1::enable_if<testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, typename std::__1::decay<_Tp>::type> >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >, testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >::value, int>::type <anonymous> > testing::OnceAction<Result(Args ...)>::OnceAction(Callable&&) [with Callable = std::__1::tuple<testing::OnceAction<int()>&&>; typename std::__1::enable_if<testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, typename std::__1::decay<_Tp>::type> >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >, testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >::value, int>::type <anonymous> = <missing>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2384:43:   required by substitution of 'template<class _Tp, class ... _Args> typename std::__1::__select_2nd<decltype (std::__1::move((_Tp)((declval<_Args>)()...))), std::__1::integral_constant<bool, true> >::type std::__1::__is_constructible_test(_Tp&&, _Args&& ...) [with _Tp = std::__1::tuple<testing::OnceAction<int()>&&>; _Args = {std::__1::tuple<testing::OnceAction<int()>&&>}]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2395:50:   required from 'struct std::__1::__libcpp_is_constructible<false, std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2443:8:   [ skipping 11 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/__tuple:290:8:   required from 'struct std::__1::__tuple_convertible<std::__1::tuple<std::__1::tuple<testing::OnceAction<int()>&&> >, std::__1::__tuple_types<testing::OnceAction<int()>&&>, true, true>'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/tuple:542:59:   required by substitution of 'template<class ... _Up, typename std::__1::enable_if<(((sizeof... (_Up) <= 1ul) && std::__1::__tuple_convertible<std::__1::tuple<_Tp ...>, typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type, std::__1::__tuple_like<typename std::__1::remove_reference<std::__1::tuple<_Tp ...> >::type>::value, std::__1::__tuple_like<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type>::value>::value) && std::__1::__all_default_constructible<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, 1ul, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul)>::type>::value), bool>::type <anonymous> > constexpr std::__1::tuple<_Tp>::tuple(_Up&& ...) [with _Up = {std::__1::tuple<testing::OnceAction<int()>&&>}; typename std::__1::enable_if<(((sizeof... (_Up) <= 1ul) && std::__1::__tuple_convertible<std::__1::tuple<_Tp ...>, typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type, std::__1::__tuple_like<typename std::__1::remove_reference<std::__1::tuple<_Tp ...> >::type>::value, std::__1::__tuple_like<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type>::value>::value) && std::__1::__all_default_constructible<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, 1ul, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul)>::type>::value), bool>::type <anonymous> = <missing>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/tuple:878:55:   required from 'constexpr std::__1::tuple<_Tp&& ...> std::__1::forward_as_tuple(_Tp&& ...) [with _Tp = {testing::OnceAction<int()>}]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:3801:43:   required from 'std::__1::__shared_ptr_emplace<_Tp, _Alloc>::__shared_ptr_emplace(_Alloc, _Args&& ...) [with _Args = {testing::OnceAction<int()>}; _Tp = testing::OnceAction<int()>; _Alloc = std::__1::allocator<testing::OnceAction<int()> >]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:4394:5:   required from 'static std::__1::shared_ptr<_Tp> std::__1::shared_ptr<_Tp>::make_shared(_Args&& ...) [with _Args = {testing::OnceAction<int()>}; _Tp = testing::OnceAction<int()>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:4758:40:   required from 'typename std::__1::enable_if<(! std::__1::is_array<_Tp>::value), std::__1::shared_ptr<_Tp> >::type std::__1::make_shared(_Args&& ...) [with _Tp = testing::OnceAction<int()>; _Args = {testing::OnceAction<int()>}; typename std::__1::enable_if<(! std::__1::is_array<_Tp>::value), std::__1::shared_ptr<_Tp> >::type = std::__1::shared_ptr<testing::OnceAction<int()> >]'
external/googletest/googlemock/include/gmock/gmock-spec-builders.h:986:40:   required from 'testing::internal::TypedExpectation<R(Args ...)>& testing::internal::TypedExpectation<R(Args ...)>::WillOnce(testing::OnceAction<Result(Args ...)>) [with R = int; Args = {}]'
foo.cpp:21:61:   required from here
external/googletest/googlemock/include/gmock/gmock-actions.h:271:41: error: incomplete type 'testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > >' used in nested name specifier
     : std::integral_constant<bool, bool(!P::value)> {};
                                         ^
external/googletest/googlemock/include/gmock/gmock-actions.h: In instantiation of 'struct testing::internal::conjunction<testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >, testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >':
external/googletest/googlemock/include/gmock/gmock-actions.h:284:8:   required from 'struct testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, std::__1::tuple<testing::OnceAction<int()>&&> > >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >, testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >'
external/googletest/googlemock/include/gmock/gmock-actions.h:476:30:   required by substitution of 'template<class Callable, typename std::__1::enable_if<testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, typename std::__1::decay<_Tp>::type> >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >, testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >::value, int>::type <anonymous> > testing::OnceAction<Result(Args ...)>::OnceAction(Callable&&) [with Callable = std::__1::tuple<testing::OnceAction<int()>&&>; typename std::__1::enable_if<testing::internal::conjunction<testing::internal::negation<std::__1::is_same<testing::OnceAction<int()>, typename std::__1::decay<_Tp>::type> >, testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >, testing::internal::conjunction<std::__1::is_constructible<typename std::__1::decay<_Tp>::type, Callable>, testing::internal::is_callable_r_impl<void, int, typename std::__1::decay<_Tp>::type> > >::value, int>::type <anonymous> = <missing>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2384:43:   required by substitution of 'template<class _Tp, class ... _Args> typename std::__1::__select_2nd<decltype (std::__1::move((_Tp)((declval<_Args>)()...))), std::__1::integral_constant<bool, true> >::type std::__1::__is_constructible_test(_Tp&&, _Args&& ...) [with _Tp = std::__1::tuple<testing::OnceAction<int()>&&>; _Args = {std::__1::tuple<testing::OnceAction<int()>&&>}]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2395:50:   required from 'struct std::__1::__libcpp_is_constructible<false, std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2443:8:   required from 'struct std::__1::__is_constructible_void_check<false, std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/type_traits:2469:30:   [ skipping 11 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/tuple:542:59:   required by substitution of 'template<class ... _Up, typename std::__1::enable_if<(((sizeof... (_Up) <= 1ul) && std::__1::__tuple_convertible<std::__1::tuple<_Tp ...>, typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type, std::__1::__tuple_like<typename std::__1::remove_reference<std::__1::tuple<_Tp ...> >::type>::value, std::__1::__tuple_like<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type>::value>::value) && std::__1::__all_default_constructible<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, 1ul, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul)>::type>::value), bool>::type <anonymous> > constexpr std::__1::tuple<_Tp>::tuple(_Up&& ...) [with _Up = {std::__1::tuple<testing::OnceAction<int()>&&>}; typename std::__1::enable_if<(((sizeof... (_Up) <= 1ul) && std::__1::__tuple_convertible<std::__1::tuple<_Tp ...>, typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type, std::__1::__tuple_like<typename std::__1::remove_reference<std::__1::tuple<_Tp ...> >::type>::value, std::__1::__tuple_like<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul), 0ul>::type>::value>::value) && std::__1::__all_default_constructible<typename std::__1::__make_tuple_types<std::__1::tuple<testing::OnceAction<int()>&&>, 1ul, ((sizeof... (_Up) < 1ul) ? sizeof... (_Up) : 1ul)>::type>::value), bool>::type <anonymous> = <missing>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/tuple:878:55:   required from 'constexpr std::__1::tuple<_Tp&& ...> std::__1::forward_as_tuple(_Tp&& ...) [with _Tp = {testing::OnceAction<int()>}]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:3801:43:   required from 'std::__1::__shared_ptr_emplace<_Tp, _Alloc>::__shared_ptr_emplace(_Alloc, _Args&& ...) [with _Args = {testing::OnceAction<int()>}; _Tp = testing::OnceAction<int()>; _Alloc = std::__1::allocator<testing::OnceAction<int()> >]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:4394:5:   required from 'static std::__1::shared_ptr<_Tp> std::__1::shared_ptr<_Tp>::make_shared(_Args&& ...) [with _Args = {testing::OnceAction<int()>}; _Tp = testing::OnceAction<int()>]'
/<redacted>/external/qnx/target/qnx7/usr/include/c++/v1/memory:4758:40:   required from 'typename std::__1::enable_if<(! std::__1::is_array<_Tp>::value), std::__1::shared_ptr<_Tp> >::type std::__1::make_shared(_Args&& ...) [with _Tp = testing::OnceAction<int()>; _Args = {testing::OnceAction<int()>}; typename std::__1::enable_if<(! std::__1::is_array<_Tp>::value), std::__1::shared_ptr<_Tp> >::type = std::__1::shared_ptr<testing::OnceAction<int()> >]'
external/googletest/googlemock/include/gmock/gmock-spec-builders.h:986:40:   required from 'testing::internal::TypedExpectation<R(Args ...)>& testing::internal::TypedExpectation<R(Args ...)>::WillOnce(testing::OnceAction<Result(Args ...)>) [with R = int; Args = {}]'
foo.cpp:21:61:   required from here
external/googletest/googlemock/include/gmock/gmock-actions.h:284:8: error: 'value' is not a member of 'testing::internal::negation<testing::internal::conjunction<std::__1::is_constructible<std::__1::tuple<testing::OnceAction<int()>&&>, std::__1::tuple<testing::OnceAction<int()>&&> >, testing::internal::is_callable_r_impl<void, int, std::__1::tuple<testing::OnceAction<int()>&&> > > >'
 struct conjunction<P1, Ps...>
        ^
cc: /<redacted>/external/qnx/host/linux/x86_64/usr/lib/gcc/aarch64-unknown-nto-qnx7.0.0/5.4.0/cc1plus error 1
Target //:foo failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 2.591s, Critical Path: 1.25s
INFO: 5 processes: 5 internal.
FAILED: Build did NOT complete successfully
mjvankampen commented 2 years ago

Same issue here with latest QNX (gcc 8.3.0 based) under Windows with CMake

derekmauro commented 2 years ago

QNX isn't officially supported. We would like a patch from the community to fix this issue.

tntljc commented 1 year ago

Same issue here with latest QNX (gcc 8.3.0 based) under Linux with CMake

Primer81 commented 5 months ago

Same issue using latest google-test V1.14.0 with QNX 7.1 qcc 8.3.0 under Windows 10 with CMake. Downgrading to google-test V1.11.0 seems to fix the issue for me.

malgorzatagora commented 3 months ago

Hi, does anyone know if a patch fixing that issue is available?

clanghans commented 5 days ago

Debugged into this but couldn't find the issue.

In case anybody is interested, boiled down the code to reproduce the issue below.

#include <gmock/gmock.h>
#include <gtest/gtest.h>

int main (int argc, char *argv[]) {
  auto fn = [](){return 0;};

  testing::OnceAction<int()> once(fn); 
  testing::OnceAction<int()> second(std::move(once));

  std::tuple<testing::OnceAction<int()>> t1(fn);
  std::tuple<testing::OnceAction<int()>> t2(std::move(t1));

  return 0;
}
#include <gmock/gmock.h>
#include <gtest/gtest.h> 

int main (int argc, char *argv[]){ 
  using k = std::__1::is_constructible<
      std::__1::tuple<testing::OnceAction<int()>>, 
      std::__1::tuple<testing::OnceAction<int()>> 
    >; 
  return sizeof(k);
}