Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
0.23.0
-
None
-
3
Description
The purpose of this ticket is to document a very cryptic error message (actually a warning that gets propagated by -Werror) that gets generated by clang-3.5 from gmock source code when trying to mock a perfectly innocent-looking function.
Problem
The following code is attempting to mock a MesosExecutorDriver:
class MockMesosExecutorDriver : public MesosExecutorDriver { public: MockMesosExecutorDriver(mesos::Executor* executor) : MesosExecutorDriver(executor) {} MOCK_METHOD1(sendStatusUpdate, Status(const TaskStatus&)); };
The above code generates the following error message:
In file included from ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock.h:58: In file included from ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:46: ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10: error: indirection of non-volatile null pointer will be deleted, not trap [-Werror,-Wnull-dereference] return *static_cast<typename remove_reference<T>::type*>(__null); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:78:22: note: in instantiation of function template specialization 'testing::internal::Invalid<mesos::Status>' requested here return internal::Invalid<T>(); ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-actions.h:190:43: note: in instantiation of member function 'testing::internal::BuiltInDefaultValue<mesos::Status>::Get' requested here internal::BuiltInDefaultValue<T>::Get() : *value_; ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1435:34: note: in instantiation of member function 'testing::DefaultValue<mesos::Status>::Get' requested here return DefaultValue<Result>::Get(); ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1334:22: note: in instantiation of member function 'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus &)>::PerformDefaultAction' requested here func_mocker->PerformDefaultAction(args, call_description)); ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-spec-builders.h:1448:26: note: in instantiation of function template specialization 'testing::internal::ActionResultHolder<mesos::Status>::PerformDefaultAction<mesos::Status (const mesos::TaskStatus &)>' requested here return ResultHolder::PerformDefaultAction(this, args, call_description); ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/gmock-generated-function-mockers.h:81:7: note: in instantiation of member function 'testing::internal::FunctionMockerBase<mesos::Status (const mesos::TaskStatus &)>::UntypedPerformDefaultAction' requested here class FunctionMocker<R(A1)> : public ^ ../3rdparty/libprocess/3rdparty/gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h:355:10: note: consider using __builtin_trap() or qualifying pointer with 'volatile' return *static_cast<typename remove_reference<T>::type*>(__null); ^
The source of the issue here is that Status is an enum. In gmock-1.6.0/include/gmock/internal/gmock-internal-utils.h you can find the following function:
template <typename T>
T Invalid() {
return *static_cast<typename remove_reference<T>::type*>(NULL);
}
This function gets called with the return type of a mocked function. In our case, the return type of the mocked function is Status.
Attempting to compile the following minimal example with clang-3.5 reproduces the error message:
#include <type_traits> template <typename T> T invalid() { return *static_cast<typename std::remove_reference<T>::type *>(nullptr); } enum E { A, B }; int main() { invalid<E>(); }
- See it online on GCC Explorer
Note that if the type is not an enum, the warning is not generated. This is why existing mocked functions that return non-enum types such as Future<void> does not encounter this issue.
Solutions
The simplest solution is to add -Wno-null-deference to mesos_tests_CPPFLAGS in src/Makefile.am.
mesos_tests_CPPFLAGS = $(MESOS_CPPFLAGS) -Wno-null-dereference
Another solution is to upgrade gmock from 1.6 to 1.7 because this problem is solved in the newer versions.
In gmock 1.7
template <typename T> inline T Invalid() { return const_cast<typename remove_reference<T>::type&>( *static_cast<volatile typename remove_reference<T>::type*>(NULL)); }
Add volatile could avoid this warning. https://goo.gl/opCiLC
Attachments
Issue Links
- is related to
-
MESOS-1073 Upgrade gmock from 1.6 to 1.7 and set C++11 support
- Resolved